/** * Resolve URI via base URL and parent element. Resolve URI based considering xml:base and * baseURI. * * @param baseURI Base URI used to fetch the XML document * @param parent Parent element from which to consider xml:base * @param url URL to be resolved */ public static String resolveURI(final String baseURI, final Parent parent, String url) { if (!resolveURIs) { return url; } if (isRelativeURI(url)) { if (".".equals(url) || "./".equals(url)) { url = ""; } if (url.startsWith("/") && baseURI != null) { String base = null; final int slashslash = baseURI.indexOf("//"); final int nextslash = baseURI.indexOf("/", slashslash + 2); if (nextslash != -1) { base = baseURI.substring(0, nextslash); } return formURI(base, url); } // Relative URI with parent if (parent != null && parent instanceof Element) { // Do we have an xml:base? String xmlbase = ((Element) parent).getAttributeValue("base", Namespace.XML_NAMESPACE); if (xmlbase != null && xmlbase.trim().length() > 0) { if (isAbsoluteURI(xmlbase)) { // Absolute xml:base, so form URI right now if (url.startsWith("/")) { // Host relative URI final int slashslash = xmlbase.indexOf("//"); final int nextslash = xmlbase.indexOf("/", slashslash + 2); if (nextslash != -1) { xmlbase = xmlbase.substring(0, nextslash); } return formURI(xmlbase, url); } if (!xmlbase.endsWith("/")) { // Base URI is filename, strip it off xmlbase = xmlbase.substring(0, xmlbase.lastIndexOf("/")); } return formURI(xmlbase, url); } else { // Relative xml:base, so walk up tree return resolveURI( baseURI, parent.getParent(), stripTrailingSlash(xmlbase) + "/" + stripStartingSlash(url)); } } // No xml:base so walk up tree return resolveURI(baseURI, parent.getParent(), url); // Relative URI with no parent (i.e. top of tree), so form URI // right now } else if (parent == null || parent instanceof Document) { return formURI(baseURI, url); } } return url; }
NodeList getElementsByTagNameNS( final Parent xshadow, final String namespaceURI, final String localName) { if (localName == null) { return EMPTYLIST; } if (namespaceURI == null) { return EMPTYLIST; } final boolean alluri = "*".equals(namespaceURI); final boolean allname = "*".equals(localName); final ArrayList<JElement> enodes = new ArrayList<JElement>(); if (xshadow != null) { final Iterator<org.jdom2.Element> it = xshadow.getDescendants(Filters.element()); org.jdom2.Element e = null; if (xshadow instanceof org.jdom2.Element) { e = (org.jdom2.Element) xshadow; } else { if (it.hasNext()) { e = it.next(); } } while (e != null) { if ((allname || localName.equals(e.getName())) && (alluri || namespaceURI.equals(e.getNamespaceURI()))) { enodes.add(find(e)); } e = it.hasNext() ? it.next() : null; } } return new JNodeList(enodes); }
NodeList getElementsByTagName(final Parent xshadow, final String tagname) { if (tagname == null) { return EMPTYLIST; } final ArrayList<JElement> enodes = new ArrayList<JElement>(); if (xshadow != null) { final Iterator<org.jdom2.Element> it = xshadow.getDescendants(Filters.element()); org.jdom2.Element e = null; if (xshadow instanceof org.jdom2.Element) { e = (org.jdom2.Element) xshadow; } else { if (it.hasNext()) { e = it.next(); } } while (e != null) { if ("*".equals(tagname) || tagname.equals(e.getQualifiedName())) { enodes.add(find(e)); } e = it.hasNext() ? it.next() : null; } } return new JNodeList(enodes); }
@Test public void testDeepNesting() { // need to get beyond 16 levels of XML. DocType dt = new DocType("root"); Element root = new Element("root"); Document doc = new Document(); doc.addContent(dt); doc.addContent(root); String xmldec = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; String dtdec = "<!DOCTYPE root>"; String lf = "\n"; StringBuilder raw = new StringBuilder(); raw.append(xmldec).append(lf).append(dtdec); StringBuilder pretty = new StringBuilder(); pretty.append(xmldec).append(lf).append(dtdec); if (!usesrawxmlout) { // most test systems use the XMLOutputter in raw mode to output // the results of the conversion. In Raw mode the XMLOutputter will // not make pretty content outside of the root element (but it will // put the XMLDeclaration on it's own line). // so, in the cases where the actual pretty format is used, we add // this newline after the DocType... pretty.append(lf); } raw.append("<root>"); pretty.append("<root>"); pretty.append(lf); final int depth = 40; int cnt = depth; Parent parent = root; StringBuilder indent = new StringBuilder(); while (--cnt > 0) { Element emt = new Element("emt"); parent.getContent().add(emt); parent = emt; raw.append("<emt>"); indent.append(" "); pretty.append(indent.toString()); pretty.append("<emt>"); pretty.append(lf); } parent.getContent().add(new Element("bottom")); raw.append("<bottom />"); pretty.append(indent.toString()); pretty.append(" <bottom />"); pretty.append(lf); cnt = depth; while (--cnt > 0) { raw.append("</emt>"); pretty.append(indent.toString()); pretty.append("</emt>"); indent.setLength(indent.length() - 2); pretty.append(lf); } raw.append("</root>"); raw.append(lf); pretty.append("</root>"); pretty.append(lf); checkOutput( doc, raw.toString(), raw.toString(), pretty.toString(), pretty.toString(), pretty.toString()); }