void XMLWriter::declareAttributeNamespaces(const Attributes& attributes) { for (int i = 0; i < attributes.getLength(); i++) { XMLString namespaceURI = attributes.getURI(i); XMLString localName = attributes.getLocalName(i); XMLString qname = attributes.getQName(i); if (!localName.empty()) { XMLString prefix; XMLString splitLocalName; Name::split(qname, prefix, splitLocalName); if (prefix.empty()) prefix = _namespaces.getPrefix(namespaceURI); if (prefix.empty() && !namespaceURI.empty() && !_namespaces.isMapped(namespaceURI)) { prefix = newPrefix(); _namespaces.declarePrefix(prefix, namespaceURI); } const XMLString& uri = _namespaces.getURI(prefix); if ((uri.empty() || uri != namespaceURI) && !namespaceURI.empty()) { _namespaces.declarePrefix(prefix, namespaceURI); } } } }
void MarkupFormatter::appendAttribute(StringBuilder& result, const Element& element, const Attribute& attribute, Namespaces* namespaces) { bool documentIsHTML = serializeAsHTMLDocument(element); QualifiedName prefixedName = attribute.name(); if (documentIsHTML && !attributeIsInSerializedNamespace(attribute)) { result.append(' '); result.append(attribute.name().localName()); } else { if (attribute.namespaceURI() == XMLNSNames::xmlnsNamespaceURI) { if (!attribute.prefix() && attribute.localName() != xmlnsAtom) prefixedName.setPrefix(xmlnsAtom); if (namespaces) { // Account for the namespace attribute we're about to append. const AtomicString& lookupKey = (!attribute.prefix()) ? emptyAtom : attribute.localName(); namespaces->set(lookupKey, attribute.value()); } } else if (attribute.namespaceURI() == XMLNames::xmlNamespaceURI) { if (!attribute.prefix()) prefixedName.setPrefix(xmlAtom); } else { if (attribute.namespaceURI() == XLinkNames::xlinkNamespaceURI) { if (!attribute.prefix()) prefixedName.setPrefix(xlinkAtom); } if (namespaces && shouldAddNamespaceAttribute(attribute, element)) { if (!prefixedName.prefix()) { // This behavior is in process of being standardized. See crbug.com/248044 and https://www.w3.org/Bugs/Public/show_bug.cgi?id=24208 String prefixPrefix("ns", 2); for (unsigned i = attribute.namespaceURI().impl()->existingHash(); ; ++i) { AtomicString newPrefix(String(prefixPrefix + String::number(i))); AtomicString foundURI = namespaces->get(newPrefix); if (foundURI == attribute.namespaceURI() || foundURI == nullAtom) { // We already generated a prefix for this namespace. prefixedName.setPrefix(newPrefix); break; } } } ASSERT(prefixedName.prefix()); appendNamespace(result, prefixedName.prefix(), attribute.namespaceURI(), *namespaces); } } result.append(' '); result.append(prefixedName.toString()); } result.append('='); if (element.isURLAttribute(attribute)) { appendQuotedURLAttributeValue(result, element, attribute); } else { result.append('"'); appendAttributeValue(result, attribute.value(), documentIsHTML); result.append('"'); } }
void XMLWriter::writeStartElement(const XMLString& namespaceURI, const XMLString& localName, const XMLString& qname, const Attributes& attributes) { if (!_nsContextPushed) _namespaces.pushContext(); _nsContextPushed = false; ++_elementCount; writeMarkup(MARKUP_LT); if (!localName.empty() && (qname.empty() || localName == qname)) { XMLString prefix; if (!namespaceURI.empty() && !_namespaces.isMapped(namespaceURI)) { prefix = newPrefix(); _namespaces.declarePrefix(prefix, namespaceURI); } else prefix = _namespaces.getPrefix(namespaceURI); writeName(prefix, localName); } else if (namespaceURI.empty() && localName.empty() && !qname.empty()) { writeXML(qname); } else if (!localName.empty() && !qname.empty()) { XMLString local; XMLString prefix; Name::split(qname, prefix, local); if (prefix.empty()) prefix = _namespaces.getPrefix(namespaceURI); const XMLString& uri = _namespaces.getURI(prefix); if ((uri.empty() || uri != namespaceURI) && !namespaceURI.empty()) { _namespaces.declarePrefix(prefix, namespaceURI); } writeName(prefix, localName); } else throw XMLException("Tag mismatch", nameToString(localName, qname)); declareAttributeNamespaces(attributes); AttributeMap attributeMap; addNamespaceAttributes(attributeMap); addAttributes(attributeMap, attributes, namespaceURI); writeAttributes(attributeMap); _unclosedStartTag = true; }