/** * Returns the Attr[]s to be output for the given element. <br> * The code of this method is a copy of {@link #handleAttributes(Element, NameSpaceSymbTable)}, * whereas it takes into account that subtree-c14n is -- well -- subtree-based. So if the element * in question isRoot of c14n, it's parent is not in the node set, as well as all other ancestors. * * @param element * @param ns * @return the Attr[]s to be output * @throws CanonicalizationException */ @Override protected Iterator<Attr> handleAttributesSubtree(Element element, NameSpaceSymbTable ns) throws CanonicalizationException { if (!element.hasAttributes() && !firstCall) { return null; } // result will contain the attrs which have to be output final SortedSet<Attr> result = this.result; result.clear(); if (element.hasAttributes()) { NamedNodeMap attrs = element.getAttributes(); int attrsLength = attrs.getLength(); for (int i = 0; i < attrsLength; i++) { Attr attribute = (Attr) attrs.item(i); String NUri = attribute.getNamespaceURI(); String NName = attribute.getLocalName(); String NValue = attribute.getValue(); if (!XMLNS_URI.equals(NUri)) { // It's not a namespace attr node. Add to the result and continue. result.add(attribute); } else if (!(XML.equals(NName) && XML_LANG_URI.equals(NValue))) { // The default mapping for xml must not be output. Node n = ns.addMappingAndRender(NName, NValue, attribute); if (n != null) { // Render the ns definition result.add((Attr) n); if (C14nHelper.namespaceIsRelative(attribute)) { Object exArgs[] = {element.getTagName(), NName, attribute.getNodeValue()}; throw new CanonicalizationException("c14n.Canonicalizer.RelativeNamespace", exArgs); } } } } } if (firstCall) { // It is the first node of the subtree // Obtain all the namespaces defined in the parents, and added to the output. ns.getUnrenderedNodes(result); // output the attributes in the xml namespace. xmlattrStack.getXmlnsAttr(result); firstCall = false; } return result.iterator(); }
Shuttle(Shuttle cp, Element e) { this.node = e; this.g = cp.g; this.svgRoot = cp.svgRoot; this.shape = cp.shape; this.clip = cp.clip; this.fontSize = cp.fontSize; this.fontFamily = cp.fontFamily; this.stroke = cp.stroke; this.fill = cp.fill; this.strokeWidth = cp.strokeWidth; this.transform = new AffineTransform(cp.transform); this.opacity = cp.opacity; if (e.hasAttributes()) { NamedNodeMap atts = e.getAttributes(); for (int i = 0; i < atts.getLength(); ++i) { Attr att = Attr.class.cast(atts.item(i)); if (att.getNamespaceURI() != null) continue; String s = att.getName(); String value = att.getValue(); if (s.equals("style")) { for (String styles : value.split("[;]+")) { int j = styles.indexOf(':'); if (j != -1) { applyStyle(styles.substring(0, j).trim(), styles.substring(j + 1).trim()); } } } else { applyStyle(s, att.getValue()); } } } }
public static void copyAttributes(SOAPElement target, Element source) { // easy way out: no attributes if (!source.hasAttributes()) return; final boolean traceEnabled = log.isTraceEnabled(); // traverse attributes NamedNodeMap attributes = source.getAttributes(); for (int i = 0, n = attributes.getLength(); i < n; i++) { Node attribute = attributes.item(i); String namespaceURI = attribute.getNamespaceURI(); // isn't the attribute a namespace declaration? if (!BpelConstants.NS_XMLNS.equals(namespaceURI)) { String name = attribute.getNodeName(); String value = attribute.getNodeValue(); if (namespaceURI == null) { /* * use the DOM level 1 method as some SAAJ implementations complain * when presented a null namespace URI */ target.setAttribute(name, value); } else { target.setAttributeNS(namespaceURI, name, value); } if (traceEnabled) log.trace("set attribute: " + name); } } }
public static void copyNamespaces(SOAPElement target, Element source) throws SOAPException { // easy way out: no attributes if (!source.hasAttributes()) return; final boolean traceEnabled = log.isTraceEnabled(); // traverse attributes to discover namespace declarations NamedNodeMap attributes = source.getAttributes(); for (int i = 0, n = attributes.getLength(); i < n; i++) { Node attribute = attributes.item(i); // is attribute a namespace declaration? if (!BpelConstants.NS_XMLNS.equals(attribute.getNamespaceURI())) continue; // namespace declaration format xmlns:prefix="namespaceURI" | // xmlns="defaultNamespaceURI" String namespaceURI = attribute.getNodeValue(); String prefix = attribute.getLocalName(); // non-default namespace declaration? if (!"xmlns".equals(prefix)) { // BPEL-195: prevent addition matching visible declaration at target if (namespaceURI.equals(target.getNamespaceURI(prefix))) continue; target.addNamespaceDeclaration(prefix, namespaceURI); if (traceEnabled) log.trace("added namespace declaration: " + prefix + "->" + namespaceURI); } // non-empty default namespace declaration else if (namespaceURI.length() > 0) { prefix = generatePrefix(source, DEFAULT_NAMESPACE_PREFIX); target.addNamespaceDeclaration(prefix, namespaceURI); if (traceEnabled) log.trace("reassigned default namespace declaration: " + prefix + "->" + namespaceURI); } } }
public static void copyNamespaces(final Element target, Element source) { // easy way out: no attributes if (!source.hasAttributes()) return; final boolean traceEnabled = log.isTraceEnabled(); // traverse attributes to discover namespace declarations NamedNodeMap attributes = source.getAttributes(); for (int i = 0, n = attributes.getLength(); i < n; i++) { Node attribute = attributes.item(i); // is attribute a namespace declaration? if (!BpelConstants.NS_XMLNS.equals(attribute.getNamespaceURI())) continue; // namespace declaration format xmlns:prefix="namespaceURI" | // xmlns="defaultNamespaceURI" String namespaceURI = attribute.getNodeValue(); String prefix = attribute.getLocalName(); // default namespace declaration? if ("xmlns".equals(prefix)) { // BPEL-195: prevent addition matching visible declaration at target if ("".equals(getPrefix(namespaceURI, target))) continue; addNamespaceDeclaration(target, namespaceURI); if (traceEnabled) log.trace("added default namespace declaration: " + namespaceURI); } else { // BPEL-195: prevent addition matching visible declaration at target if (prefix.equals(getPrefix(namespaceURI, target))) continue; addNamespaceDeclaration(target, namespaceURI, prefix); if (traceEnabled) log.trace("added namespace declaration: " + prefix + "->" + namespaceURI); } } }
protected void handleParent(Element e, NameSpaceSymbTable ns) { if (!e.hasAttributes() && e.getNamespaceURI() == null) { return; } xmlattrStack.push(-1); NamedNodeMap attrs = e.getAttributes(); int attrsLength = attrs.getLength(); for (int i = 0; i < attrsLength; i++) { Attr attribute = (Attr) attrs.item(i); String NName = attribute.getLocalName(); String NValue = attribute.getNodeValue(); if (Constants.NamespaceSpecNS.equals(attribute.getNamespaceURI())) { if (!XML.equals(NName) || !Constants.XML_LANG_SPACE_SpecNS.equals(NValue)) { ns.addMapping(NName, NValue, attribute); } } else if (!"id".equals(NName) && XML_LANG_URI.equals(attribute.getNamespaceURI())) { xmlattrStack.addXmlnsAttr(attribute); } } if (e.getNamespaceURI() != null) { String NName = e.getPrefix(); String NValue = e.getNamespaceURI(); String Name; if (NName == null || NName.equals("")) { NName = "xmlns"; Name = "xmlns"; } else { Name = "xmlns:" + NName; } Attr n = e.getOwnerDocument().createAttributeNS("http://www.w3.org/2000/xmlns/", Name); n.setValue(NValue); ns.addMapping(NName, NValue, n); } }
void handleParent(Element e, NameSpaceSymbTable ns) { if (!e.hasAttributes()) { return; } xmlattrStack.push(-1); NamedNodeMap attrs = e.getAttributes(); int attrsLength = attrs.getLength(); for (int i = 0; i < attrsLength; i++) { Attr N = (Attr) attrs.item(i); if (Constants.NamespaceSpecNS != N.getNamespaceURI()) { // Not a namespace definition, ignore. if (XML_LANG_URI == N.getNamespaceURI()) { xmlattrStack.addXmlnsAttr(N); } continue; } String NName = N.getLocalName(); String NValue = N.getNodeValue(); if (XML.equals(NName) && Constants.XML_LANG_SPACE_SpecNS.equals(NValue)) { continue; } ns.addMapping(NName, NValue, N); } }
@Override public void relink_namespace(ThreadContext context) { Element e = (Element) node; e.getOwnerDocument().renameNode(e, e.lookupNamespaceURI(e.getPrefix()), e.getNodeName()); if (e.hasAttributes()) { NamedNodeMap attrs = e.getAttributes(); for (int i = 0; i < attrs.getLength(); i++) { Attr attr = (Attr) attrs.item(i); String nsUri = ""; String prefix = attr.getPrefix(); String nodeName = attr.getNodeName(); if ("xml".equals(prefix)) { nsUri = "http://www.w3.org/XML/1998/namespace"; } else if ("xmlns".equals(prefix) || nodeName.equals("xmlns")) { nsUri = "http://www.w3.org/2000/xmlns/"; } else { nsUri = attr.lookupNamespaceURI(nodeName); } e.getOwnerDocument().renameNode(attr, nsUri, nodeName); } } if (e.hasChildNodes()) { ((XmlNodeSet) children(context)).relink_namespace(context); } }
/** * Float the xml:* attributes of the unselected parent nodes to the ciurrent node. * * @param E * @param result */ private void addXmlAttributes(Element E, SortedSet result) { /* The processing of an element node E MUST be modified slightly when an * XPath node-set is given as input and the element's parent is omitted * from the node-set. The method for processing the attribute axis of an * element E in the node-set is enhanced. All element nodes along E's * ancestor axis are examined for nearest occurrences of attributes in * the xml namespace, such as xml:lang and xml:space (whether or not they * are in the node-set). From this list of attributes, remove any that are * in E's attribute axis (whether or not they are in the node-set). Then, * lexicographically merge this attribute list with the nodes of E's * attribute axis that are in the node-set. The result of visiting the * attribute axis is computed by processing the attribute nodes in this * merged attribute list. */ // E is in the node-set Node parent = E.getParentNode(); Map loa = new HashMap(); if ((parent != null) && (parent.getNodeType() == Node.ELEMENT_NODE) && !isVisible(parent)) { // parent element is not in node set for (Node ancestor = parent; (ancestor != null) && (ancestor.getNodeType() == Node.ELEMENT_NODE); ancestor = ancestor.getParentNode()) { Element el = ((Element) ancestor); if (!el.hasAttributes()) { continue; } // for all ancestor elements NamedNodeMap ancestorAttrs = el.getAttributes(); for (int i = 0; i < ancestorAttrs.getLength(); i++) { // for all attributes in the ancestor element Attr currentAncestorAttr = (Attr) ancestorAttrs.item(i); if (XML_LANG_URI.equals(currentAncestorAttr.getNamespaceURI())) { // do we have an xml:* ? if (!E.hasAttributeNS(XML_LANG_URI, currentAncestorAttr.getLocalName())) { // the xml:* attr is not in E if (!loa.containsKey(currentAncestorAttr.getName())) { loa.put(currentAncestorAttr.getName(), currentAncestorAttr); } } } } } } result.addAll(loa.values()); }
/** * This is the work horse for {@link #circumventBug2650}. * * @param node * @see <A HREF="http://nagoya.apache.org/bugzilla/show_bug.cgi?id=2650">Namespace axis resolution * is not XPath compliant </A> */ private static void circumventBug2650internal(Node node) { Node parent = null; Node sibling = null; final String namespaceNs = Constants.NamespaceSpecNS; do { switch (node.getNodeType()) { case Node.ELEMENT_NODE: Element element = (Element) node; if (!element.hasChildNodes()) break; if (element.hasAttributes()) { NamedNodeMap attributes = element.getAttributes(); int attributesLength = attributes.getLength(); for (Node child = element.getFirstChild(); child != null; child = child.getNextSibling()) { if (child.getNodeType() != Node.ELEMENT_NODE) { continue; } Element childElement = (Element) child; for (int i = 0; i < attributesLength; i++) { Attr currentAttr = (Attr) attributes.item(i); if (namespaceNs != currentAttr.getNamespaceURI()) continue; if (childElement.hasAttributeNS(namespaceNs, currentAttr.getLocalName())) { continue; } childElement.setAttributeNS( namespaceNs, currentAttr.getName(), currentAttr.getNodeValue()); } } } case Node.ENTITY_REFERENCE_NODE: case Node.DOCUMENT_NODE: parent = node; sibling = node.getFirstChild(); break; } while ((sibling == null) && (parent != null)) { sibling = parent.getNextSibling(); parent = parent.getParentNode(); } ; if (sibling == null) { return; } node = sibling; sibling = node.getNextSibling(); } while (true); }
public static void copyAttributes(Element target, Element source) { // easy way out: no attributes if (!source.hasAttributes()) return; // traverse attributes NamedNodeMap attributes = source.getAttributes(); for (int i = 0, n = attributes.getLength(); i < n; i++) { Node attribute = attributes.item(i); String namespaceURI = attribute.getNamespaceURI(); // isn't the attribute a namespace declaration? if (!BpelConstants.NS_XMLNS.equals(namespaceURI)) { target.setAttributeNS(namespaceURI, attribute.getNodeName(), attribute.getNodeValue()); } } }
private void serialize(Element e, XmlSerializer s, int depth, String spaces) throws Exception { String name = e.getTagName(); writeSpace(s, depth, spaces); s.startTag("", name); if (e.hasAttributes()) { NamedNodeMap nm = e.getAttributes(); for (int i = 0; i < nm.getLength(); i++) { Attr attr = (Attr) nm.item(i); s.attribute("", attr.getName(), attr.getValue()); } } if (e.hasChildNodes()) { NodeList nl = e.getChildNodes(); int elements = 0; for (int i = 0; i < nl.getLength(); i++) { Node n = nl.item(i); short type = n.getNodeType(); switch (type) { case Node.ELEMENT_NODE: serialize((Element) n, s, depth + 1, spaces); elements++; break; case Node.TEXT_NODE: s.text(text(n)); break; case Node.CDATA_SECTION_NODE: s.cdsect(text(n)); break; } } if (elements > 0) { writeSpace(s, depth, spaces); } } s.endTag("", name); }
public static void removeAttributes(Element elem) { if (elem.hasAttributes()) { NamedNodeMap attributeMap = elem.getAttributes(); // since node maps are live, we must hold them in a separate container int n = attributeMap.getLength(); Attr[] attributes = new Attr[n]; for (int i = 0; i < n; i++) { attributes[i] = (Attr) attributeMap.item(i); } // now remove each attribute from the element for (int i = 0; i < n; i++) { elem.removeAttributeNode(attributes[i]); } } }
/** * Adds to ns the definitons from the parent elements of el * * @param el * @param ns */ static final void getParentNameSpaces(Element el, NameSpaceSymbTable ns) { List parents = new ArrayList(); Node n1 = el.getParentNode(); if (!(n1 instanceof Element)) { return; } // Obtain all the parents of the elemnt Element parent = (Element) el.getParentNode(); while (parent != null) { parents.add(parent); Node n = parent.getParentNode(); if (!(n instanceof Element)) { break; } parent = (Element) n; } // Visit them in reverse order. ListIterator it = parents.listIterator(parents.size()); while (it.hasPrevious()) { Element ele = (Element) it.previous(); if (!ele.hasAttributes()) { continue; } NamedNodeMap attrs = ele.getAttributes(); int attrsLength = attrs.getLength(); for (int i = 0; i < attrsLength; i++) { Attr N = (Attr) attrs.item(i); if (!Constants.NamespaceSpecNS.equals(N.getNamespaceURI())) { // Not a namespace definition, ignore. continue; } String NName = N.getLocalName(); String NValue = N.getNodeValue(); if (XML.equals(NName) && Constants.XML_LANG_SPACE_SpecNS.equals(NValue)) { continue; } ns.addMapping(NName, NValue, N); } } Attr nsprefix; if (((nsprefix = ns.getMappingWithoutRendered("xmlns")) != null) && "".equals(nsprefix.getValue())) { ns.addMappingAndRender("xmlns", "", nullNode); } }
static final void getSetRec( final Node rootNode, final Set result, final Node exclude, final boolean com) { // Set result = new HashSet(); if (rootNode == exclude) { return; } switch (rootNode.getNodeType()) { case Node.ELEMENT_NODE: result.add(rootNode); Element el = (Element) rootNode; if (el.hasAttributes()) { NamedNodeMap nl = ((Element) rootNode).getAttributes(); for (int i = 0; i < nl.getLength(); i++) { result.add(nl.item(i)); } } // no return keep working case Node.DOCUMENT_NODE: for (Node r = rootNode.getFirstChild(); r != null; r = r.getNextSibling()) { if (r.getNodeType() == Node.TEXT_NODE) { result.add(r); while ((r != null) && (r.getNodeType() == Node.TEXT_NODE)) { r = r.getNextSibling(); } if (r == null) return; } getSetRec(r, result, exclude, com); } return; case Node.COMMENT_NODE: if (com) { result.add(rootNode); } return; case Node.DOCUMENT_TYPE_NODE: return; default: result.add(rootNode); } return; }
private static int getElementBySearching(Node root, String id, Element[] els) { switch (root.getNodeType()) { case Node.ELEMENT_NODE: Element el = (Element) root; if (el.hasAttributes()) { int index = names.indexOf(el.getNamespaceURI()); if (index < 0) { index = 4; } if (el.getAttribute("Id").equals(id)) { els[index] = el; if (index == 0) { return 1; } } else if (el.getAttribute("id").equals(id)) { if (index != 2) { index = 4; } els[index] = el; } else if (el.getAttribute("ID").equals(id)) { if (index != 3) { index = 4; } els[index] = el; } else if ((index == 3) && (el.getAttribute("OriginalRequestID").equals(id) || el.getAttribute("RequestID").equals(id) || el.getAttribute("ResponseID").equals(id))) { els[3] = el; } } case Node.DOCUMENT_NODE: Node sibling = root.getFirstChild(); while (sibling != null) { if (getElementBySearching(sibling, id, els) == 1) return 1; sibling = sibling.getNextSibling(); } } return 0; }
/** * Float the xml:* attributes of the parent nodes to the root node of c14n * * @param E the root node. * @param result the xml:* attributes to output. */ private void addXmlAttributesSubtree(Element E, SortedSet result) { // E is in the node-set Node parent = E.getParentNode(); Map loa = new HashMap(); if ((parent != null) && (parent.getNodeType() == Node.ELEMENT_NODE)) { // parent element is not in node set for (Node ancestor = parent; (ancestor != null) && (ancestor.getNodeType() == Node.ELEMENT_NODE); ancestor = ancestor.getParentNode()) { Element el = ((Element) ancestor); if (!el.hasAttributes()) { continue; } // for all ancestor elements NamedNodeMap ancestorAttrs = el.getAttributes(); for (int i = 0; i < ancestorAttrs.getLength(); i++) { // for all attributes in the ancestor element Attr currentAncestorAttr = (Attr) ancestorAttrs.item(i); if (XML_LANG_URI.equals(currentAncestorAttr.getNamespaceURI())) { // do we have an xml:* ? if (!E.hasAttributeNS(XML_LANG_URI, currentAncestorAttr.getLocalName())) { // the xml:* attr is not in E if (!loa.containsKey(currentAncestorAttr.getName())) { loa.put(currentAncestorAttr.getName(), currentAncestorAttr); } } } } } } result.addAll(loa.values()); }
/** * INTERNAL: When using the DOM Platform during unmarshal operations. Use the element to determine * if the element represents a null value. @ param element * * @return true if based on the element it represents a null value, else false. */ public boolean valueIsNull(Element element) { // Check Nillable: Ignore any other attributes that are in addition to xsi:nil if (null == element) { return true; } else { if (isNullRepresentedByXsiNil() && element.hasAttributeNS( javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_NIL_ATTRIBUTE)) { return true; } else { // EMPTY_NODE - Required // Verify no attributes and no child nodes on the DOM element if (isNullRepresentedByEmptyNode() && !element.hasAttributes() && (element.getChildNodes().getLength() == 0)) { return true; } else { return false; } } } }
/** * Returns the Attr[]s to be output for the given element. <br> * IMPORTANT: This method expects to work on a modified DOM tree, i.e. a DOM which has been * prepared using {@link org.apache.xml.security.utils.XMLUtils#circumventBug2650( * org.w3c.dom.Document)}. * * @param element * @param ns * @return the Attr[]s to be output * @throws CanonicalizationException */ @Override protected Iterator<Attr> handleAttributes(Element element, NameSpaceSymbTable ns) throws CanonicalizationException { // result will contain the attrs which have to be output xmlattrStack.push(ns.getLevel()); boolean isRealVisible = isVisibleDO(element, ns.getLevel()) == 1; final SortedSet<Attr> result = this.result; result.clear(); if (element.hasAttributes()) { NamedNodeMap attrs = element.getAttributes(); int attrsLength = attrs.getLength(); for (int i = 0; i < attrsLength; i++) { Attr attribute = (Attr) attrs.item(i); String NUri = attribute.getNamespaceURI(); String NName = attribute.getLocalName(); String NValue = attribute.getValue(); if (!XMLNS_URI.equals(NUri)) { // A non namespace definition node. if (XML_LANG_URI.equals(NUri)) { if (NName.equals("id")) { if (isRealVisible) { // treat xml:id like any other attribute // (emit it, but don't inherit it) result.add(attribute); } } else { xmlattrStack.addXmlnsAttr(attribute); } } else if (isRealVisible) { // The node is visible add the attribute to the list of output attributes. result.add(attribute); } } else if (!XML.equals(NName) || !XML_LANG_URI.equals(NValue)) { /* except omit namespace node with local name xml, which defines * the xml prefix, if its string value is * http://www.w3.org/XML/1998/namespace. */ // add the prefix binding to the ns symb table. if (isVisible(attribute)) { if (isRealVisible || !ns.removeMappingIfRender(NName)) { // The xpath select this node output it if needed. Node n = ns.addMappingAndRender(NName, NValue, attribute); if (n != null) { result.add((Attr) n); if (C14nHelper.namespaceIsRelative(attribute)) { Object exArgs[] = {element.getTagName(), NName, attribute.getNodeValue()}; throw new CanonicalizationException( "c14n.Canonicalizer.RelativeNamespace", exArgs); } } } } else { if (isRealVisible && !XMLNS.equals(NName)) { ns.removeMapping(NName); } else { ns.addMapping(NName, NValue, attribute); } } } } } if (isRealVisible) { // The element is visible, handle the xmlns definition Attr xmlns = element.getAttributeNodeNS(XMLNS_URI, XMLNS); Node n = null; if (xmlns == null) { // No xmlns def just get the already defined. n = ns.getMapping(XMLNS); } else if (!isVisible(xmlns)) { // There is a definition but the xmlns is not selected by the xpath. // then xmlns="" n = ns.addMappingAndRender(XMLNS, "", nullNode); } // output the xmlns def if needed. if (n != null) { result.add((Attr) n); } // Float all xml:* attributes of the unselected parent elements to this one. xmlattrStack.getXmlnsAttr(result); ns.getUnrenderedNodes(result); } return result.iterator(); }
protected static String nodeToString(Node node, Set<String> parentPrefixes, String namespaceURI) throws Exception { StringBuilder b = new StringBuilder(); if (node == null) { return ""; } if (node instanceof Element) { Element element = (Element) node; b.append("<"); b.append(element.getNodeName()); Map<String, String> thisLevelPrefixes = new HashMap<>(); if (element.getPrefix() != null && !parentPrefixes.contains(element.getPrefix())) { thisLevelPrefixes.put(element.getPrefix(), element.getNamespaceURI()); } if (element.hasAttributes()) { NamedNodeMap map = element.getAttributes(); for (int i = 0; i < map.getLength(); i++) { Node attr = map.item(i); if (attr.getNodeName().startsWith("xmlns")) continue; if (attr.getPrefix() != null && !parentPrefixes.contains(attr.getPrefix())) { thisLevelPrefixes.put(attr.getPrefix(), element.getNamespaceURI()); } b.append(" "); b.append(attr.getNodeName()); b.append("=\""); b.append(attr.getNodeValue()); b.append("\""); } } if (namespaceURI != null && !thisLevelPrefixes.containsValue(namespaceURI) && !namespaceURI.equals(element.getParentNode().getNamespaceURI())) { b.append(" xmlns=\"").append(namespaceURI).append("\""); } for (Map.Entry<String, String> entry : thisLevelPrefixes.entrySet()) { b.append(" xmlns:") .append(entry.getKey()) .append("=\"") .append(entry.getValue()) .append("\""); parentPrefixes.add(entry.getKey()); } NodeList children = element.getChildNodes(); boolean hasOnlyAttributes = true; for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); if (child.getNodeType() != Node.ATTRIBUTE_NODE) { hasOnlyAttributes = false; break; } } if (!hasOnlyAttributes) { b.append(">"); for (int i = 0; i < children.getLength(); i++) { b.append( nodeToString(children.item(i), parentPrefixes, children.item(i).getNamespaceURI())); } b.append("</"); b.append(element.getNodeName()); b.append(">"); } else { b.append("/>"); } for (String thisLevelPrefix : thisLevelPrefixes.keySet()) { parentPrefixes.remove(thisLevelPrefix); } } else if (node.getNodeValue() != null) { b.append(encodeText(node.getNodeValue(), node instanceof Attr)); } return b.toString(); }
/** * Returns the Attr[]s to be outputted for the given element. <br> * IMPORTANT: This method expects to work on a modified DOM tree, i.e. a DOM which has been * prepared using {@link * com.sun.org.apache.xml.internal.security.utils.XMLUtils#circumventBug2650( * org.w3c.dom.Document)}. * * @param E * @param ns * @return the Attr[]s to be outputted * @throws CanonicalizationException */ Iterator handleAttributes(Element E, NameSpaceSymbTable ns) throws CanonicalizationException { // result will contain the attrs which have to be outputted xmlattrStack.push(ns.getLevel()); boolean isRealVisible = isVisibleDO(E, ns.getLevel()) == 1; NamedNodeMap attrs = null; int attrsLength = 0; if (E.hasAttributes()) { attrs = E.getAttributes(); attrsLength = attrs.getLength(); } SortedSet result = this.result; result.clear(); for (int i = 0; i < attrsLength; i++) { Attr N = (Attr) attrs.item(i); String NUri = N.getNamespaceURI(); if (XMLNS_URI != NUri) { // A non namespace definition node. if (XML_LANG_URI == NUri) { xmlattrStack.addXmlnsAttr(N); } else if (isRealVisible) { // The node is visible add the attribute to the list of output attributes. result.add(N); } // keep working continue; } String NName = N.getLocalName(); String NValue = N.getValue(); if ("xml".equals(NName) && XML_LANG_URI.equals(NValue)) { /* except omit namespace node with local name xml, which defines * the xml prefix, if its string value is http://www.w3.org/XML/1998/namespace. */ continue; } // add the prefix binding to the ns symb table. // ns.addInclusiveMapping(NName,NValue,N,isRealVisible); if (isVisible(N)) { if (!isRealVisible && ns.removeMappingIfRender(NName)) { continue; } // The xpath select this node output it if needed. // Node n=ns.addMappingAndRenderXNodeSet(NName,NValue,N,isRealVisible); Node n = ns.addMappingAndRender(NName, NValue, N); if (n != null) { result.add(n); if (C14nHelper.namespaceIsRelative(N)) { Object exArgs[] = {E.getTagName(), NName, N.getNodeValue()}; throw new CanonicalizationException("c14n.Canonicalizer.RelativeNamespace", exArgs); } } } else { if (isRealVisible && NName != XMLNS) { ns.removeMapping(NName); } else { ns.addMapping(NName, NValue, N); } } } if (isRealVisible) { // The element is visible, handle the xmlns definition Attr xmlns = E.getAttributeNodeNS(XMLNS_URI, XMLNS); Node n = null; if (xmlns == null) { // No xmlns def just get the already defined. n = ns.getMapping(XMLNS); } else if (!isVisible(xmlns)) { // There is a definition but the xmlns is not selected by the xpath. // then xmlns="" n = ns.addMappingAndRender(XMLNS, "", nullNode); } // output the xmlns def if needed. if (n != null) { result.add(n); } // Float all xml:* attributes of the unselected parent elements to this one. // addXmlAttributes(E,result); xmlattrStack.getXmlnsAttr(result); ns.getUnrenderedNodes(result); } return result.iterator(); }
/** * Called to serialize a DOM element. Equivalent to calling {@link #startElement}, {@link * #endElement} and serializing everything inbetween, but better optimized. */ protected void serializeElement(Element elem) throws IOException { Attr attr; NamedNodeMap attrMap; int i; Node child; ElementState state; String name; String value; String tagName; String prefix, localUri; String uri; if (fNamespaces) { // local binder stores namespace declaration // that has been printed out during namespace fixup of // the current element fLocalNSBinder.reset(); // add new namespace context fNSBinder.pushContext(); } if (DEBUG) { System.out.println( "==>startElement: " + elem.getNodeName() + " ns=" + elem.getNamespaceURI()); } tagName = elem.getTagName(); state = getElementState(); if (isDocumentState()) { // If this is the root element handle it differently. // If the first root element in the document, serialize // the document's DOCTYPE. Space preserving defaults // to that of the output format. if (!_started) { startDocument(tagName); } } else { // For any other element, if first in parent, then // close parent's opening tag and use the parent's // space preserving. if (state.empty) _printer.printText('>'); // Must leave CData section first if (state.inCData) { _printer.printText("]]>"); state.inCData = false; } // Indent this element on a new line if the first // content of the parent element or immediately // following an element. if (_indenting && !state.preserveSpace && (state.empty || state.afterElement || state.afterComment)) _printer.breakLine(); } // Do not change the current element state yet. // This only happens in endElement(). fPreserveSpace = state.preserveSpace; int length = 0; attrMap = null; // retrieve attributes if (elem.hasAttributes()) { attrMap = elem.getAttributes(); length = attrMap.getLength(); } if (!fNamespaces) { // no namespace fixup should be performed // serialize element name _printer.printText('<'); _printer.printText(tagName); _printer.indent(); // For each attribute print it's name and value as one part, // separated with a space so the element can be broken on // multiple lines. for (i = 0; i < length; ++i) { attr = (Attr) attrMap.item(i); name = attr.getName(); value = attr.getValue(); if (value == null) value = ""; printAttribute(name, value, attr.getSpecified(), attr); } } else { // do namespace fixup // REVISIT: some optimization could probably be done to avoid traversing // attributes twice. // // --------------------------------------- // record all valid namespace declarations // before attempting to fix element's namespace // --------------------------------------- for (i = 0; i < length; i++) { attr = (Attr) attrMap.item(i); uri = attr.getNamespaceURI(); // check if attribute is a namespace decl if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) { value = attr.getNodeValue(); if (value == null) { value = XMLSymbols.EMPTY_STRING; } if (value.equals(NamespaceContext.XMLNS_URI)) { if (fDOMErrorHandler != null) { String msg = DOMMessageFormatter.formatMessage( DOMMessageFormatter.XML_DOMAIN, "CantBindXMLNS", null); modifyDOMError(msg, DOMError.SEVERITY_ERROR, null, attr); boolean continueProcess = fDOMErrorHandler.handleError(fDOMError); if (!continueProcess) { // stop the namespace fixup and validation throw new RuntimeException( DOMMessageFormatter.formatMessage( DOMMessageFormatter.SERIALIZER_DOMAIN, "SerializationStopped", null)); } } } else { prefix = attr.getPrefix(); prefix = (prefix == null || prefix.length() == 0) ? XMLSymbols.EMPTY_STRING : fSymbolTable.addSymbol(prefix); String localpart = fSymbolTable.addSymbol(attr.getLocalName()); if (prefix == XMLSymbols.PREFIX_XMLNS) { // xmlns:prefix value = fSymbolTable.addSymbol(value); // record valid decl if (value.length() != 0) { fNSBinder.declarePrefix(localpart, value); } else { // REVISIT: issue error on invalid declarations // xmlns:foo = "" } continue; } else { // xmlns // empty prefix is always bound ("" or some string) value = fSymbolTable.addSymbol(value); fNSBinder.declarePrefix(XMLSymbols.EMPTY_STRING, value); continue; } } // end-else: valid declaration } // end-if: namespace declaration } // end-for // ----------------------- // get element uri/prefix // ----------------------- uri = elem.getNamespaceURI(); prefix = elem.getPrefix(); // ---------------------- // output element name // ---------------------- // REVISIT: this could be removed if we always convert empty string to null // for the namespaces. if ((uri != null && prefix != null) && uri.length() == 0 && prefix.length() != 0) { // uri is an empty string and element has some prefix // the namespace alg later will fix up the namespace attributes // remove element prefix prefix = null; _printer.printText('<'); _printer.printText(elem.getLocalName()); _printer.indent(); } else { _printer.printText('<'); _printer.printText(tagName); _printer.indent(); } // --------------------------------------------------------- // Fix up namespaces for element: per DOM L3 // Need to consider the following cases: // // case 1: <foo:elem xmlns:ns1="myURI" xmlns="default"/> // Assume "foo", "ns1" are declared on the parent. We should not miss // redeclaration for both "ns1" and default namespace. To solve this // we add a local binder that stores declaration only for current element. // This way we avoid outputing duplicate declarations for the same element // as well as we are not omitting redeclarations. // // case 2: <elem xmlns="" xmlns="default"/> // We need to bind default namespace to empty string, to be able to // omit duplicate declarations for the same element // // case 3: <xsl:stylesheet xmlns:xsl="http://xsl"> // We create another element body bound to the "http://xsl" namespace // as well as namespace attribute rebounding xsl to another namespace. // <xsl:body xmlns:xsl="http://another"> // Need to make sure that the new namespace decl value is changed to // "http://xsl" // // --------------------------------------------------------- // check if prefix/namespace is correct for current element // --------------------------------------------------------- if (uri != null) { // Element has a namespace uri = fSymbolTable.addSymbol(uri); prefix = (prefix == null || prefix.length() == 0) ? XMLSymbols.EMPTY_STRING : fSymbolTable.addSymbol(prefix); if (fNSBinder.getURI(prefix) == uri) { // The xmlns:prefix=namespace or xmlns="default" was declared at parent. // The binder always stores mapping of empty prefix to "". // (NOTE: local binder does not store this kind of binding!) // Thus the case where element was declared with uri="" (with or without a prefix) // will be covered here. } else { // the prefix is either undeclared // or // conflict: the prefix is bound to another URI if (fNamespacePrefixes) { printNamespaceAttr(prefix, uri); } fLocalNSBinder.declarePrefix(prefix, uri); fNSBinder.declarePrefix(prefix, uri); } } else { // Element has no namespace if (elem.getLocalName() == null) { // DOM Level 1 node! if (fDOMErrorHandler != null) { String msg = DOMMessageFormatter.formatMessage( DOMMessageFormatter.DOM_DOMAIN, "NullLocalElementName", new Object[] {elem.getNodeName()}); modifyDOMError(msg, DOMError.SEVERITY_ERROR, null, elem); boolean continueProcess = fDOMErrorHandler.handleError(fDOMError); // REVISIT: should we terminate upon request? if (!continueProcess) { throw new RuntimeException( DOMMessageFormatter.formatMessage( DOMMessageFormatter.SERIALIZER_DOMAIN, "SerializationStopped", null)); } } } else { // uri=null and no colon (DOM L2 node) uri = fNSBinder.getURI(XMLSymbols.EMPTY_STRING); if (uri != null && uri.length() > 0) { // there is a default namespace decl that is bound to // non-zero length uri, output xmlns="" if (fNamespacePrefixes) { printNamespaceAttr(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING); } fLocalNSBinder.declarePrefix(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING); fNSBinder.declarePrefix(XMLSymbols.EMPTY_STRING, XMLSymbols.EMPTY_STRING); } } } // ----------------------------------------- // Fix up namespaces for attributes: per DOM L3 // check if prefix/namespace is correct the attributes // ----------------------------------------- for (i = 0; i < length; i++) { attr = (Attr) attrMap.item(i); value = attr.getValue(); name = attr.getNodeName(); uri = attr.getNamespaceURI(); // Fix attribute that was declared with a prefix and namespace="" if (uri != null && uri.length() == 0) { uri = null; // we must remove prefix for this attribute name = attr.getLocalName(); } if (DEBUG) { System.out.println("==>process attribute: " + attr.getNodeName()); } // make sure that value is never null. if (value == null) { value = XMLSymbols.EMPTY_STRING; } if (uri != null) { // attribute has namespace !=null prefix = attr.getPrefix(); prefix = prefix == null ? XMLSymbols.EMPTY_STRING : fSymbolTable.addSymbol(prefix); String localpart = fSymbolTable.addSymbol(attr.getLocalName()); // --------------------------------------------------- // print namespace declarations namespace declarations // --------------------------------------------------- if (uri != null && uri.equals(NamespaceContext.XMLNS_URI)) { // check if we need to output this declaration prefix = attr.getPrefix(); prefix = (prefix == null || prefix.length() == 0) ? XMLSymbols.EMPTY_STRING : fSymbolTable.addSymbol(prefix); localpart = fSymbolTable.addSymbol(attr.getLocalName()); if (prefix == XMLSymbols.PREFIX_XMLNS) { // xmlns:prefix localUri = fLocalNSBinder.getURI(localpart); // local prefix mapping value = fSymbolTable.addSymbol(value); if (value.length() != 0) { if (localUri == null) { // declaration was not printed while fixing element namespace binding // If the DOM Level 3 namespace-prefixes feature is set to false // do not print xmlns attributes if (fNamespacePrefixes) { printNamespaceAttr(localpart, value); } // case 4: <elem xmlns:xx="foo" xx:attr=""/> // where attribute is bound to "bar". // If the xmlns:xx is output here first, later we should not // redeclare "xx" prefix. Instead we would pick up different prefix // for the attribute. // final: <elem xmlns:xx="foo" NS1:attr="" xmlns:NS1="bar"/> fLocalNSBinder.declarePrefix(localpart, value); } } else { // REVISIT: issue error on invalid declarations // xmlns:foo = "" } continue; } else { // xmlns // empty prefix is always bound ("" or some string) uri = fNSBinder.getURI(XMLSymbols.EMPTY_STRING); localUri = fLocalNSBinder.getURI(XMLSymbols.EMPTY_STRING); value = fSymbolTable.addSymbol(value); if (localUri == null) { // declaration was not printed while fixing element namespace binding if (fNamespacePrefixes) { printNamespaceAttr(XMLSymbols.EMPTY_STRING, value); } // case 4 does not apply here since attributes can't use // default namespace } continue; } } uri = fSymbolTable.addSymbol(uri); // find if for this prefix a URI was already declared String declaredURI = fNSBinder.getURI(prefix); if (prefix == XMLSymbols.EMPTY_STRING || declaredURI != uri) { // attribute has no prefix (default namespace decl does not apply to attributes) // OR // attribute prefix is not declared // OR // conflict: attr URI does not match the prefix in scope name = attr.getNodeName(); // Find if any prefix for attributes namespace URI is available // in the scope String declaredPrefix = fNSBinder.getPrefix(uri); if (declaredPrefix != null && declaredPrefix != XMLSymbols.EMPTY_STRING) { // use the prefix that was found prefix = declaredPrefix; name = prefix + ":" + localpart; } else { if (DEBUG) { System.out.println("==> cound not find prefix for the attribute: " + prefix); } if (prefix != XMLSymbols.EMPTY_STRING && fLocalNSBinder.getURI(prefix) == null) { // the current prefix is not null and it has no in scope declaration // use this prefix } else { // find a prefix following the pattern "NS" +index (starting at 1) // make sure this prefix is not declared in the current scope. int counter = 1; prefix = fSymbolTable.addSymbol(PREFIX + counter++); while (fLocalNSBinder.getURI(prefix) != null) { prefix = fSymbolTable.addSymbol(PREFIX + counter++); } name = prefix + ":" + localpart; } // add declaration for the new prefix if (fNamespacePrefixes) { printNamespaceAttr(prefix, uri); } value = fSymbolTable.addSymbol(value); fLocalNSBinder.declarePrefix(prefix, value); fNSBinder.declarePrefix(prefix, uri); } // change prefix for this attribute } printAttribute( name, (value == null) ? XMLSymbols.EMPTY_STRING : value, attr.getSpecified(), attr); } else { // attribute uri == null if (attr.getLocalName() == null) { if (fDOMErrorHandler != null) { String msg = DOMMessageFormatter.formatMessage( DOMMessageFormatter.DOM_DOMAIN, "NullLocalAttrName", new Object[] {attr.getNodeName()}); modifyDOMError(msg, DOMError.SEVERITY_ERROR, null, attr); boolean continueProcess = fDOMErrorHandler.handleError(fDOMError); if (!continueProcess) { // stop the namespace fixup and validation throw new RuntimeException( DOMMessageFormatter.formatMessage( DOMMessageFormatter.SERIALIZER_DOMAIN, "SerializationStopped", null)); } } printAttribute(name, value, attr.getSpecified(), attr); } else { // uri=null and no colon // no fix up is needed: default namespace decl does not // apply to attributes printAttribute(name, value, attr.getSpecified(), attr); } } } // end loop for attributes } // end namespace fixup algorithm // If element has children, then serialize them, otherwise // serialize en empty tag. if (elem.hasChildNodes()) { // Enter an element state, and serialize the children // one by one. Finally, end the element. state = enterElementState(null, null, tagName, fPreserveSpace); state.doCData = _format.isCDataElement(tagName); state.unescaped = _format.isNonEscapingElement(tagName); child = elem.getFirstChild(); while (child != null) { serializeNode(child); child = child.getNextSibling(); } if (fNamespaces) { fNSBinder.popContext(); } endElementIO(null, null, tagName); } else { if (DEBUG) { System.out.println("==>endElement: " + elem.getNodeName()); } if (fNamespaces) { fNSBinder.popContext(); } _printer.unindent(); _printer.printText("/>"); // After element but parent element is no longer empty. state.afterElement = true; state.afterComment = false; state.empty = false; if (isDocumentState()) _printer.flush(); } }