Przeglądaj źródła

LibXML: Set XMLNS namespace for xmlns attribute

This is what Blink and Gecko do, and is required for serialization
(innerHTML etc.) of XML elements to work.
Maciej 11 miesięcy temu
rodzic
commit
cad3b085a8

+ 2 - 0
Tests/LibWeb/Text/expected/DOM/DOMParser-xmlns.txt

@@ -0,0 +1,2 @@
+namespaceURI=http://www.w3.org/2000/xmlns/ prefix=null localName=xmlns value=http://www.w3.org/2000/svg
+namespaceURI=http://www.w3.org/2000/xmlns/ prefix=xmlns localName=test value=foo

+ 11 - 0
Tests/LibWeb/Text/input/DOM/DOMParser-xmlns.html

@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<script src="../include.js"></script>
+<script>
+    test(() => {
+        const svgstr = `<svg xmlns="http://www.w3.org/2000/svg" xmlns:test="foo"></svg>`;
+        const svg = new DOMParser().parseFromString(svgstr, "image/svg+xml").documentElement;
+        for (const attr of svg.attributes) {
+            println(`namespaceURI=${attr.namespaceURI} prefix=${attr.prefix} localName=${attr.localName} value=${attr.value}`);
+        }
+    });
+</script>

+ 8 - 1
Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp

@@ -86,8 +86,15 @@ void XMLDocumentBuilder::element_start(const XML::Name& name, HashMap<XML::Name,
         MUST(m_current_node->append_child(node));
     }
 
-    for (auto const& attribute : attributes)
+    for (auto const& attribute : attributes) {
+        // https://www.w3.org/TR/2006/REC-xml-names11-20060816/#ns-decl
+        if (attribute.key == "xmlns" || attribute.key.starts_with("xmlns:"sv)) {
+            auto name = attribute.key;
+            // The prefix xmlns is used only to declare namespace bindings and is by definition bound to the namespace name http://www.w3.org/2000/xmlns/.
+            MUST(node->set_attribute_ns(Namespace::XMLNS, MUST(FlyString::from_deprecated_fly_string(name)), MUST(String::from_byte_string(attribute.value))));
+        }
         MUST(node->set_attribute(MUST(FlyString::from_deprecated_fly_string(attribute.key)), MUST(String::from_byte_string(attribute.value))));
+    }
 
     m_current_node = node.ptr();
 }