@Test public void testAddOrSetAttributeAttributesImplNode() throws ParserConfigurationException { final AttributesImpl atts = new AttributesImpl(); final DOMImplementation dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().getDOMImplementation(); final Document doc = dom.createDocument(null, "foo", null); doc.getDocumentElement().setAttribute("foo", "foo"); final Attr att = (Attr) doc.getDocumentElement().getAttributeNode("foo"); XMLUtils.addOrSetAttribute(atts, att); final int i = atts.getIndex(NULL_NS_URI, "foo"); assertEquals(NULL_NS_URI, atts.getURI(i)); assertEquals("foo", atts.getQName(i)); assertEquals("foo", atts.getLocalName(i)); assertEquals("foo", atts.getValue(i)); doc.getDocumentElement().setAttributeNS(XML_NS_URI, "xml:lang", "en"); final Attr lang = (Attr) doc.getDocumentElement().getAttributeNodeNS(XML_NS_URI, "lang"); XMLUtils.addOrSetAttribute(atts, lang); final int l = atts.getIndex(XML_NS_URI, "lang"); assertEquals(XML_NS_URI, atts.getURI(l)); assertEquals("xml:lang", atts.getQName(l)); assertEquals("lang", atts.getLocalName(l)); assertEquals("en", atts.getValue(l)); }
/** Retrieve and remove the namespaces declarations from the list of attributes. */ private Attributes extractNamespaces(Attributes attrs) throws SAXException { AttributesImpl attrsOnly; String rawName; int i; int indexColon; String prefix; int length; if (attrs == null) { return null; } length = attrs.getLength(); attrsOnly = new AttributesImpl(attrs); for (i = length - 1; i >= 0; --i) { rawName = attrsOnly.getQName(i); // We have to exclude the namespaces declarations from the attributes // Append only when the feature http://xml.org/sax/features/namespace-prefixes" // is TRUE if (rawName.startsWith("xmlns")) { if (rawName.length() == 5) { startPrefixMapping("", attrs.getValue(i)); attrsOnly.removeAttribute(i); } else if (rawName.charAt(5) == ':') { startPrefixMapping(rawName.substring(6), attrs.getValue(i)); attrsOnly.removeAttribute(i); } } } return attrsOnly; }
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { Set<String> mapped = new HashSet<String>(); mappedPrefixes.push(mapped); AttributesImpl newAtts = new AttributesImpl(); // parse namespace declaration attributes if (atts != null) { for (int i = 0; i < atts.getLength(); i++) { String attQname = atts.getQName(i); boolean addAtt = true; if (isNamespaceDeclaration(attQname)) { String newPrefix = ""; String newUri = atts.getValue(i); if (attQname.length() > NAMESPACE_DECLARATION_PREFIX.length()) { newPrefix = attQname.substring(NAMESPACE_DECLARATION_PREFIX.length() + 1); } // xmlns prefix cannot be declared if (NAMESPACE_DECLARATION_PREFIX.equals(newPrefix)) throwException( NAMESPACE_DECLARATION_PREFIX + " namespace prefix cannot be declared"); // xml cannot be bound to a different uri if (XML_PREFIX.equals(newPrefix)) { if (!XML_URI.equals(newUri)) throwException( XML_PREFIX + " namespace prefix cannot be bound to an URI different from " + XML_URI); } // no prefix except for xml can be bound to xml // namespace else if (XML_URI.equals(newUri)) throwException( "only " + XML_PREFIX + " namespace prefix can be bound to " + XML_URI); // check that new prefix is an ncname if (newPrefix.length() > 0 && !XMLChar.isValidNCName(newPrefix)) throwException("namespace prefix " + newPrefix + " is not an NCName"); if (mapped.contains(newPrefix)) throwException( "namespace prefix " + newPrefix + " declared twice in the same element"); Mapping mapping = new Mapping(newUri, prefixMappings.get(newPrefix)); prefixMappings.put(newPrefix, mapping); mapped.add(newPrefix); contentHandler.startPrefixMapping(newPrefix, newUri); addAtt = namespacePrefixes; } if (addAtt) newAtts.addAttribute("", "", attQname, atts.getType(i), atts.getValue(i)); } } // set uris on attributes for (int i = 0; i < newAtts.getLength(); i++) { String attQname = newAtts.getQName(i); ExpandedName splitName = parseQName(attQname); newAtts.setLocalName(i, splitName.localName); newAtts.setURI(i, splitName.uri); } ExpandedName splitName = parseQName(qName); localName = splitName.localName; uri = splitName.uri; contentHandler.startElement(uri, localName, qName, newAtts); }