TL;DR: Why can I end up with a DOM that serializes to this?
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:test="http://example.com/test"
xmlns:test="http://example.com/test">
...
</svg>
I need to modify an SVG graphic that is inlined into a HTML page, which involves adding elements and attributes using a namespace, http://example.com/test which shall be bound to the prefix test.
The original SVG document may have no such namespace:
<svg id="img" xmlns="http://www.w3.org/2000/svg">...</svg>
Or it might already by declared like this:
<svg id="img" xmlns="http://www.w3.org/2000/svg" xmlns:test="http://example.com/test">...</svg>
So I think I need to add the namespace to the svg root element like that:
svgRoot.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:test", "http://example.com/test");
I was careless and executed this line on each document, no matter if the namespace was already declared or not, because I thought I would just overwrite it with the same content. But now I have lots of documents which have 0, 1 or 2 of the the same namespace declarations.
What's even more confusing, if my source document has 2 or more of those identical namespace declarations, and I add 1, 2 or even more afterwards, in the end the total sum of identical namespace declarations is always 2, never more than that.
This behavior is identical across Firefox 92, Chrome 93 and Safari 14, so it seems like it's intended. Anyway, the Web Developer DOM Inspector in Firefox somehow gets stuck and stops updating the DOM when the second namespace declaration is added.
Here's a minimal example for the 2 + 2 = 2 case. Note that I removed the code where I actually use the namespace binding for brevity:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Namespace Test</title>
</head>
<body>
This is an SVG graphic:<br />
<svg id="img"
xmlns="http://www.w3.org/2000/svg"
xmlns:test="http://example.com/test"
xmlns:test="http://example.com/test">
<ellipse cx="240" cy="50" rx="220" ry="30" style="fill:yellow" />
</svg>
<script>
var svgRoot = document.getElementById("img");
svgRoot.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:test", "http://example.com/test");
svgRoot.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:test", "http://example.com/test");
alert("Result: " + svgRoot.outerHTML);
</script>
</body>
</html>