Duplicate xmlns attributes should be combined?
hubgit opened this issue · 3 comments
I'm not sure whether this is a bug in w3c-xmlserializer
or whether the current behaviour matches the spec and browsers implement the spec differently.
When an xmlns
attribute is set manually on an element, even if it's set to the same value as the node's namespace URI, w3c-xmlserializer
repeats the xmlns
attribute.
Browsers:
const element = document.createElementNS('http://example.com', 'div')
element.setAttribute('xmlns', 'http://example.com')
const serializer = new XMLSerializer()
console.log(serializer.serializeToString(element))
// <div xmlns="http://example.com"/>
w3c-xmlserializer:
import { XMLSerializer } from 'w3c-xmlserializer'
const element = document.createElementNS('http://example.com', 'div')
element.setAttribute('xmlns', 'http://example.com')
const serializer = new XMLSerializer.interface()
console.log(serializer.serializeToString(element))
// <div xmlns="http://example.com" xmlns="http://example.com"/>
I note that setting requireWellFormed
to true
(i.e. calling produceXMLSerialization(element, true)
) throws an "InvalidStateError: Failed to serialize XML: Invalid attribute localName value" error, because it explicitly forbids attributes named xmlns
that aren't in the http://www.w3.org/2000/xmlns/
namespace, so this may be valid, but maybe it should match the behaviour of the browsers' native XMLSerializer?
I had a read through the spec, and w3c‑xmlserializer
is technically correct, but this behaviour might not be web compatible.
This is causing issues for me as well.
w3c-xmlserializer has different output depending on whether it's being used with jsdom or a web browser.
- jsdom sets namespaceURI on an xmlns attribute.
- web browser (I've tested Chrome and Firefox) leave the namespaceURI property of an xmlns attribute as null.
The result is that if used with jsdom, localDefaultNamespace in serializeElement has a value, but if used within Chrome/Firefox context, localDefaultNamespace is null.
Therefore, when paired with jsdom, only qualifiedName is appended to the markup string, whereas in Chrome/Firefox context, the full xmlns attribute is appended, which is then re-appended a second time in attributeUtils.serializeAttributes.
Yes, technically w3c-xmlserializer implements the spec, but not in the same way that Chrome/Firefox implement it.
It seems ignoreNamespaceDefAttr should be used towards end of serializeAttributes to ensure the xmlns attribute isn't set a second time. I'll submit a pull request for consideration.
This also seems to cause issues with svgdom since I also dont set a namespaceURI for the xmlns attribute (because the attribute is created using setAttribute and not setAttributeNS).
The spec says, that an xml compatible dom needs to know the xmlns namespace. Does that mean, that an xmlns attriute has to be moved to the correct namespace even though it wasnt created using the NS-version of setAttribute?