public Document nextTableRow(String atts) { // peek at current cell - stay with it IF // + it's the first cell in the row // + the current cursor points at the first child (a block) // + the block pointed by cursor is empty Element cell = peek("table-cell", "nextTableRow() is not applicable outside enclosing table"); if (cell.getPreviousSibling() == null && cursor == cell.getFirstChild() && !cursor.hasChildNodes()) { attributes((Element) cell.getParentNode(), atts); return this; } // pop to table pop("table", "nextTableRow() is not applicable outside enclosing table"); Element table = cursor; // last child is already table-body? if (table.getLastChild().getNodeName().equals("table-body")) { cursor = (Element) table.getLastChild(); } else { push("table-body"); } // add row push("table-row", atts); // add cell push("table-cell", "border=" + table.getAttribute("border")); push("block"); // done return this; }
/** * Carries out preprocessing that makes JEuclid handle the document better. * * @param doc Document */ static void preprocessForJEuclid(Document doc) { // underbrace and overbrace NodeList list = doc.getElementsByTagName("mo"); for (int i = 0; i < list.getLength(); i++) { Element mo = (Element) list.item(i); String parentName = ((Element) mo.getParentNode()).getTagName(); if (parentName == null) { continue; } if (parentName.equals("munder") && isTextChild(mo, "\ufe38")) { mo.setAttribute("stretchy", "true"); mo.removeChild(mo.getFirstChild()); mo.appendChild(doc.createTextNode("\u23df")); } else if (parentName.equals("mover") && isTextChild(mo, "\ufe37")) { mo.setAttribute("stretchy", "true"); mo.removeChild(mo.getFirstChild()); mo.appendChild(doc.createTextNode("\u23de")); } } // menclose for long division doesn't allow enough top padding. Oh, and // <mpadded> isn't implemented. And there isn't enough padding to left of // the bar either. Solve by adding an <mover> with just an <mspace> over# // the longdiv, contained within an mrow that adds a <mspace> before it. list = doc.getElementsByTagName("menclose"); for (int i = 0; i < list.getLength(); i++) { Element menclose = (Element) list.item(i); // Only for longdiv if (!"longdiv".equals(menclose.getAttribute("notation"))) { continue; } Element mrow = doc.createElementNS(WebMathsService.NS, "mrow"); Element mover = doc.createElementNS(WebMathsService.NS, "mover"); Element mspace = doc.createElementNS(WebMathsService.NS, "mspace"); Element mspaceW = doc.createElementNS(WebMathsService.NS, "mspace"); boolean previousElement = false; for (Node previous = menclose.getPreviousSibling(); previous != null; previous = previous.getPreviousSibling()) { if (previous.getNodeType() == Node.ELEMENT_NODE) { previousElement = true; break; } } if (previousElement) { mspaceW.setAttribute("width", "4px"); } menclose.getParentNode().insertBefore(mrow, menclose); menclose.getParentNode().removeChild(menclose); mrow.appendChild(mspaceW); mrow.appendChild(mover); mover.appendChild(menclose); mover.appendChild(mspace); } }
/** Add a list item */ public Document nextListItem(String format) { // <list-block> // <list-item> // <list-item-label end-indent="label-end()"><block>•</block></list-item-label> // <list-item-body start-indent="body-start()"> // <block/> // </list-item-body> // </list-item> // check containing list-block Element list = peek("list-block", "nextListItem() is not applicable outside list block"); // a list with only one item containing an empty block? if (list.getChildNodes().getLength() == 1 && cursor.getFirstChild() == null && cursor.getPreviousSibling() == null && cursor.getParentNode().getLocalName().equals("list-item-body")) { // delete list-item and start over list.removeChild(list.getFirstChild()); } // continue with list cursor = list; // find out what 'bullet' to use String label = attribute("genj:label", format); if (label != null) { // check provisional-distance-between-starts - we assume a certain 'em' per label character String dist = list.getAttribute("provisional-distance-between-starts"); if (dist.endsWith("em")) { float len = label.length() * 0.6F; if (Float.parseFloat(dist.substring(0, dist.length() - 2)) < len) list.setAttribute("provisional-distance-between-starts", len + "em"); } } else { label = "\u2219"; // • /u2219 works in JEditPane, • \u2022 doesn't } // add new item push("list-item"); push("list-item-label", "end-indent=label-end()"); push("block"); text(label, ""); pop(); pop(); push("list-item-body", "start-indent=body-start()"); push("block"); return this; }
public Document nextTableCell(String atts) { // peek at current cell - stay with it IF // + it's the first cell in the row // + the current cursor points at the first child (a block) // + the block pointed by cursor is empty Element cell = peek("table-cell", "nextTableCell() is not applicable outside enclosing table"); if (cell.getPreviousSibling() == null && cursor == cell.getFirstChild() && !cursor.hasChildNodes()) { attributes(cell, atts); // add empty content to block so another call to nextTableCell() willl actually move forward push("inline", "").pop(); return this; } // peek at row Element row = peek("table-row", "nextTableCell() is not applicable outside enclosing table row"); int cells = row.getElementsByTagName("table-cell").getLength(); // peek at table - add new row if we have all columns already Element table = peek("table", "nextTableCell() is not applicable outside enclosing table"); int cols = table.getElementsByTagName("table-column").getLength(); if (cols > 0 && cells == cols) return nextTableRow(); // pop to row pop("table-row", "nextTableCell() is not applicable outside enclosing table row"); // 20060215 wanted to use border=inherit here but that would require table-row // and table-body to have border=inherit as well. table-body can't have a // border property in a table with border-collapse=separate (which is the only // model FOP supports). // So we're simply doing our own 'inherit' here :) Alternative would be to do // us border=from-nearest-specified-value() on each cell or border=inherit // on the table-columns and then border=from-table-column() on the cells. // add now push("table-cell", "border=" + table.getAttribute("border") + "," + atts); push("block"); // done return this; }
@Test public void testWrite() throws DITAOTException, ParserConfigurationException, SAXException, IOException { /* * the part of content of conrefpush_stub2.xml is * <ol> * <li id="A">A</li> * <li id="B">B</li> * <li id="C">C</li> * </ol> * * the part of content of conrefpush_stup.xml is * <steps> * <step conaction="pushbefore"><cmd>before</cmd></step> * <step conref="conrefpush_stub2.xml#X/A" conaction="mark"/> * <step conref="conrefpush_stub2.xml#X/B" conaction="mark"/> * <step conaction="pushafter"><cmd>after</cmd></step> * <step conref="conrefpush_stub2.xml#X/C" conaction="pushreplace"><cmd>replace</cmd></step> * </steps> * * after conrefpush the part of conrefpush_stub2.xml should be like this * <ol class="- topic/ol "> * <li class="- topic/li task/step "> * <ph class="- topic/ph task/cmd "> * before * </ph> * </li> * <li id="A" class="- topic/li ">A</li> * <li id="B" class="- topic/li ">B</li> * <li class="- topic/li task/step "> * <ph class="- topic/ph task/cmd "> * after * </ph> * </li> * <li class="- topic/li task/step "> * <ph class="- topic/ph task/cmd "> * replace * </ph> * </li> * </ol> */ final ConrefPushParser parser = new ConrefPushParser(); final ConrefPushReader reader = new ConrefPushReader(); reader.read(inputFile.getAbsolutePath()); final Map<String, Hashtable<String, String>> pushSet = reader.getPushMap(); final Iterator<Map.Entry<String, Hashtable<String, String>>> iter = pushSet.entrySet().iterator(); if (iter.hasNext()) { final Map.Entry<String, Hashtable<String, String>> entry = iter.next(); // initialize the parsed file FileUtils.copyFile(new File(srcDir, "conrefpush_stub2_backup.xml"), new File(entry.getKey())); final Content content = new ContentImpl(); content.setValue(entry.getValue()); parser.setContent(content); parser.write(entry.getKey()); final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); final DocumentBuilder builder = factory.newDocumentBuilder(); final Document document = builder.parse(new File(entry.getKey())); final Element elem = document.getDocumentElement(); NodeList nodeList = elem.getChildNodes(); // according to the structure, it comes to the <li> after 2 iterations. for (int i = 0; i < 2; i++) { for (int j = 0; j < nodeList.getLength(); j++) { if (nodeList.item(j).getNodeType() == Node.ELEMENT_NODE) { nodeList = nodeList.item(j).getChildNodes(); break; } } } Element element; for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { element = (Element) node; if (element.getAttributes().getNamedItem("id") != null && element.getAttributes().getNamedItem("id").getNodeValue().equals("A")) { // get node of before node = element.getPreviousSibling(); while (node.getNodeType() != Node.ELEMENT_NODE) { node = node.getPreviousSibling(); } assertEquals( "<li class=\"- topic/li task/step \"><ph class=\"- topic/ph task/cmd \">before</ph></li>", nodeToString((Element) node)); } else if (element.getAttributes().getNamedItem("id") != null && element.getAttributes().getNamedItem("id").getNodeValue().equals("B")) { // get node of after node = element.getNextSibling(); while (node.getNodeType() != Node.ELEMENT_NODE) { node = node.getNextSibling(); } assertEquals( "<li class=\"- topic/li task/step \"><ph class=\"- topic/ph task/cmd \">after</ph></li>", nodeToString((Element) node)); // get node of replacement node = node.getNextSibling(); while (node.getNodeType() != Node.ELEMENT_NODE) { node = node.getNextSibling(); } assertEquals( "<li class=\"- topic/li task/step \" id=\"C\"><ph class=\"- topic/ph task/cmd \">replace</ph></li>", nodeToString((Element) node)); } } } } }
@Override protected void initChildren(Element eThis) throws OmException { Node nPrevious = eThis.getPreviousSibling(); if (nPrevious != null && nPrevious instanceof Text) { String sText = ((Text) nPrevious).getData(); if (sText.length() > 0 && Character.isWhitespace(sText.charAt(sText.length() - 1))) bSpaceBefore = true; } Node nAfter = eThis.getNextSibling(); if (nAfter != null && nAfter instanceof Text) { String sText = ((Text) nAfter).getData(); if (sText.length() > 0 && Character.isWhitespace(sText.charAt(0))) bSpaceAfter = true; } List<Place> lPlaces = new LinkedList<Place>(); int iPlace = 0; StringBuffer sbText = new StringBuffer(); for (Node n = eThis.getFirstChild(); n != null; n = n.getNextSibling()) { if (n instanceof Element) { Element eplace = (Element) n; if (!eplace.getTagName().equals("eplace")) throw new OmFormatException("<equation> may only contain text and <eplace> tags"); Element[] aeChildren = XML.getChildren(eplace); QComponent qcChild; boolean bImplicit = false; if (aeChildren.length != 1) // Treats more than one child as inside <t> { qcChild = getQDocument().build(this, eplace, "t"); bImplicit = true; } else // Treats single child as specific component (auto-sizing works) qcChild = getQDocument().build(this, aeChildren[0], null); addChild(qcChild); // Must be stored in standard child array so it // can be found etc. // See if width/height is specified int iWidth, iHeight; if (eplace.hasAttribute("width") && eplace.hasAttribute("height")) { try { iWidth = Integer.parseInt(eplace.getAttribute("width")); iHeight = Integer.parseInt(eplace.getAttribute("height")); } catch (NumberFormatException nfe) { throw new OmFormatException("<equation> <eplace>: width= and height= must be integers"); } } else { Dimension d = qcChild.getApproximatePixelSize(); if (d == null) throw new OmFormatException( "<equation> <eplace>: Except for components that support automatic " + "size estimation and fixing, <eplace> must include width= and height="); iWidth = d.width; iHeight = d.height; } Place p = new Place(); p.sID = "p" + (iPlace++); p.qc = qcChild; p.iWidth = iWidth; p.iHeight = iHeight; p.bImplicit = bImplicit; if (!eplace.hasAttribute("label")) throw new OmFormatException("<equation> <eplace>: Must include label="); if (eplace.hasAttribute("label")) p.sLabel = eplace.getAttribute("label"); else p.sLabel = null; if (eplace.hasAttribute("for")) p.sLabelFor = eplace.getAttribute("for"); else if (qcChild instanceof Labelable) p.sLabelFor = qcChild.getID(); lPlaces.add(p); // Add in the equation format text representing the placeholder sbText.append("\\placeholder{" + p.sID + "}{" + p.iWidth + "," + p.iHeight + "}"); } else if (n instanceof Text) { sbText.append(n.getNodeValue()); } } sEquation = sbText.toString(); apPlaces = lPlaces.toArray(new Place[0]); }
private boolean newlineBeforeElementOpen(Element element, int depth) { if (hasBlankLineAbove()) { return false; } if (mPrefs.removeEmptyLines || depth <= 0) { return false; } if (isMarkupElement(element)) { return false; } // See if this element should be separated from the previous element. // This is the case if we are not compressing whitespace (checked above), // or if we are not immediately following a comment (in which case the // newline would have been added above it), or if we are not in a formatting // style where if (mStyle == XmlFormatStyle.LAYOUT) { // In layouts we always separate elements return true; } if (mStyle == XmlFormatStyle.MANIFEST || mStyle == XmlFormatStyle.RESOURCE || mStyle == XmlFormatStyle.FILE) { Node curr = element.getPreviousSibling(); // <style> elements are traditionally separated unless it follows a comment if (TAG_STYLE.equals(element.getTagName())) { if (curr == null || curr.getNodeType() == Node.ELEMENT_NODE || (curr.getNodeType() == Node.TEXT_NODE && curr.getNodeValue().trim().isEmpty() && (curr.getPreviousSibling() == null || curr.getPreviousSibling().getNodeType() == Node.ELEMENT_NODE))) { return true; } } // In all other styles, we separate elements if they have a different tag than // the previous one (but we don't insert a newline inside tags) while (curr != null) { short nodeType = curr.getNodeType(); if (nodeType == Node.ELEMENT_NODE) { Element sibling = (Element) curr; if (!element.getTagName().equals(sibling.getTagName())) { return true; } break; } else if (nodeType == Node.TEXT_NODE) { String text = curr.getNodeValue(); if (!text.trim().isEmpty()) { break; } // If there is just whitespace, continue looking for a previous sibling } else { // Any other previous node type, such as a comment, means we don't // continue looking: this element should not be separated break; } curr = curr.getPreviousSibling(); } if (curr == null && depth <= 1) { // Insert new line inside tag if it's the first element inside the root tag return true; } return false; } return false; }