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 SVGLangSpace::addSupportedAttributes(HashSet<QualifiedName>& supportedAttributes)
{
    DEFINE_STATIC_LOCAL(AtomicString, xmlPrefix, ("xml", AtomicString::ConstructFromLiteral));

    QualifiedName langWithPrefix = XMLNames::langAttr;
    langWithPrefix.setPrefix(xmlPrefix);
    supportedAttributes.add(langWithPrefix);
    supportedAttributes.add(XMLNames::langAttr);

    QualifiedName spaceWithPrefix = XMLNames::spaceAttr;
    spaceWithPrefix.setPrefix(xmlPrefix);
    supportedAttributes.add(spaceWithPrefix);
    supportedAttributes.add(XMLNames::spaceAttr);
}
void SVGLangSpace::addSupportedAttributes(HashSet<QualifiedName>& supportedAttributes)
{
    static NeverDestroyed<AtomicString> xmlPrefix("xml", AtomicString::ConstructFromLiteral);

    QualifiedName langWithPrefix = XMLNames::langAttr;
    langWithPrefix.setPrefix(xmlPrefix);
    supportedAttributes.add(langWithPrefix);
    supportedAttributes.add(XMLNames::langAttr);

    QualifiedName spaceWithPrefix = XMLNames::spaceAttr;
    spaceWithPrefix.setPrefix(xmlPrefix);
    supportedAttributes.add(spaceWithPrefix);
    supportedAttributes.add(XMLNames::spaceAttr);
}
Exemple #4
0
void SVGURIReference::addSupportedAttributes(HashSet<QualifiedName>& supportedAttributes)
{
    DEFINE_STATIC_LOCAL(AtomicString, xlinkPrefix, ("xlink"));
    QualifiedName hrefWithPrefix = XLinkNames::hrefAttr;
    hrefWithPrefix.setPrefix(xlinkPrefix);
    supportedAttributes.add(hrefWithPrefix);
    supportedAttributes.add(XLinkNames::hrefAttr);
}
void MarkupAccumulator::appendAttribute(StringBuilder& result, const Element& element, const Attribute& attribute, Namespaces* namespaces)
{
    bool documentIsHTML = serializeAsHTMLDocument(element);

    result.append(' ');

    QualifiedName prefixedName = attribute.name();
    if (documentIsHTML && !attributeIsInSerializedNamespace(attribute)) {
        result.append(attribute.name().localName());
    } else {
        if (attribute.namespaceURI() == XLinkNames::xlinkNamespaceURI) {
            if (!attribute.prefix())
                prefixedName.setPrefix(xlinkAtom);
        } else if (attribute.namespaceURI() == XMLNames::xmlNamespaceURI) {
            if (!attribute.prefix())
                prefixedName.setPrefix(xmlAtom);
        } else if (attribute.namespaceURI() == XMLNSNames::xmlnsNamespaceURI) {
            if (attribute.name() != XMLNSNames::xmlnsAttr && !attribute.prefix())
                prefixedName.setPrefix(xmlnsAtom);
        }
        result.append(prefixedName.toString());
    }

    result.append('=');

    if (element.isURLAttribute(attribute)) {
        appendQuotedURLAttributeValue(result, element, attribute);
    } else {
        result.append('"');
        appendAttributeValue(result, attribute.value(), documentIsHTML);
        result.append('"');
    }

    if (!documentIsHTML && namespaces && shouldAddNamespaceAttribute(attribute, *namespaces))
        appendNamespace(result, prefixedName.prefix(), prefixedName.namespaceURI(), *namespaces);
}
void MarkupAccumulator::generateUniquePrefix(QualifiedName& prefixedName, const Namespaces& namespaces)
{
    // http://www.w3.org/TR/DOM-Level-3-Core/namespaces-algorithms.html#normalizeDocumentAlgo
    // Find a prefix following the pattern "NS" + index (starting at 1) and make sure this
    // prefix is not declared in the current scope.
    StringBuilder builder;
    do {
        builder.clear();
        builder.append("NS");
        builder.appendNumber(++m_prefixLevel);
        const AtomicString& name = builder.toAtomicString();
        if (!namespaces.get(name.impl())) {
            prefixedName.setPrefix(name);
            return;
        }
    } while (true);
}
void MarkupAccumulator::appendAttribute(StringBuilder& result, const Element& element, const Attribute& attribute, Namespaces* namespaces)
{
    bool documentIsHTML = element.document().isHTMLDocument();

    result.append(' ');

    QualifiedName prefixedName = attribute.name();
    if (documentIsHTML && !attributeIsInSerializedNamespace(attribute))
        result.append(attribute.name().localName());
    else {
        if (!attribute.namespaceURI().isEmpty()) {
            AtomicStringImpl* foundNS = namespaces && attribute.prefix().impl() ? namespaces->get(attribute.prefix().impl()) : 0;
            bool prefixIsAlreadyMappedToOtherNS = foundNS && foundNS != attribute.namespaceURI().impl();
            if (attribute.prefix().isEmpty() || !foundNS || prefixIsAlreadyMappedToOtherNS) {
                if (AtomicStringImpl* prefix = namespaces ? namespaces->get(attribute.namespaceURI().impl()) : 0)
                    prefixedName.setPrefix(AtomicString(prefix));
                else {
                    bool shouldBeDeclaredUsingAppendNamespace = !attribute.prefix().isEmpty() && !foundNS;
                    if (!shouldBeDeclaredUsingAppendNamespace && attribute.localName() != xmlnsAtom && namespaces)
                        generateUniquePrefix(prefixedName, *namespaces);
                }
            }
        }
        result.append(prefixedName.toString());
    }

    result.append('=');

    if (element.isURLAttribute(attribute))
        appendQuotedURLAttributeValue(result, element, attribute);
    else {
        result.append('"');
        appendAttributeValue(result, attribute.value(), documentIsHTML);
        result.append('"');
    }

    if ((inXMLFragmentSerialization() || !documentIsHTML) && namespaces && shouldAddNamespaceAttribute(attribute, *namespaces))
        appendNamespace(result, prefixedName.prefix(), prefixedName.namespaceURI(), *namespaces);
}