diff --git a/Tests/LibWeb/Text/expected/DOM/DOMParser-xmlns.txt b/Tests/LibWeb/Text/expected/DOM/DOMParser-xmlns.txt
new file mode 100644
index 00000000000..ae04f02b8d8
--- /dev/null
+++ b/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
diff --git a/Tests/LibWeb/Text/input/DOM/DOMParser-xmlns.html b/Tests/LibWeb/Text/input/DOM/DOMParser-xmlns.html
new file mode 100644
index 00000000000..bd979a25459
--- /dev/null
+++ b/Tests/LibWeb/Text/input/DOM/DOMParser-xmlns.html
@@ -0,0 +1,11 @@
+
+
+
diff --git a/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp b/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp
index a1c7f771bb3..a6dfaca4b07 100644
--- a/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp
+++ b/Userland/Libraries/LibWeb/XML/XMLDocumentBuilder.cpp
@@ -86,8 +86,15 @@ void XMLDocumentBuilder::element_start(const XML::Name& name, HashMapappend_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();
}