TL;DR:为什么我最终会得到一个序列化到此的 DOM?
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:test="http://example.com/test"
xmlns:test="http://example.com/test">
...
</svg>
我需要修改内联到 HTML 页面中的 SVG 图形,其中涉及使用命名空间 http://example.com/test
添加元素和属性,该命名空间应绑定(bind)到前缀测试
。
原始 SVG 文档可能没有这样的命名空间:
<svg id="img" xmlns="http://www.w3.org/2000/svg">...</svg>
或者它可能已经这样声明:
<svg id="img" xmlns="http://www.w3.org/2000/svg" xmlns:test="http://example.com/test">...</svg>
所以我认为我需要将命名空间添加到 svg
根元素,如下所示:
svgRoot.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:test", "http://example.com/test");
我很粗心,在每个文档上都执行了这一行,无论命名空间是否已经声明,因为我以为我会用相同的内容覆盖它。但现在我有很多文档有 0、1 或 2 个相同的命名空间声明。
更令人困惑的是,如果我的源文档有 2 个或多个相同的命名空间声明,然后我添加 1、2 个甚至更多,那么最终相同的命名空间声明的总和始终为 2,永远不会超过那个。
此行为在 Firefox 92、Chrome 93 和 Safari 14 中是相同的,因此看起来似乎是有意为之。不管怎样,当添加第二个命名空间声明时,Firefox 中的 Web Developer DOM Inspector 会不知何故卡住并停止更新 DOM。
这是 2 + 2 = 2 情况的最小示例。请注意,为了简洁起见,我删除了实际使用命名空间绑定(bind)的代码:
<!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>
最佳答案
这是因为 xmlns:test
在 SVG 命名空间中无效,因此标记中的标记将在 null
命名空间中声明。
var svgRoot = document.querySelector("svg");
console.log(svgRoot.attributes[1].namespaceURI);
This is an SVG graphic:<br />
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:test="http://example.com/test">
</svg>
然后,JS中的就会正确设置为XMLNS NameSpace:
var svgRoot = document.querySelector("svg");
// here the name space is different than in the markup
svgRoot.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:test", "http://example.com/test");
console.log(svgRoot.attributes[0].namespaceURI);
This is an SVG graphic:<br />
<svg>
</svg>
这两个属性都是从不同的命名空间设置的,它们可以共存于同一个 DOM 元素上。
关于javascript - 为什么一个 DOM 元素最多可以有两个相同的命名空间声明?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69346808/