javascript - 为什么一个 DOM 元素最多可以有两个相同的命名空间声明?
问题描述
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
应绑定到前缀test
.
原始 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案例的最小示例。请注意,为简洁起见,我删除了实际使用命名空间绑定的代码:
<!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>
这两个属性都是从不同的 NameSpace 设置的,它们可以共同存在于同一个 DOM 元素上。
推荐阅读
- xml - 取消注释 web.config 中的标记
- javascript - 调用 insertChars 后的 Fabric JS v 2.3.6,当按下任意键时设置插入符号的位置会被破坏
- r - 跨多个列的 grepl - 通配符不起作用
- spring - Spring boot默认创建admin账号
- magento - Magento 2 更改每个商店视图的价格
- c++ - 使用双包装类进行位操作(C++、clang)修复性能下降
- angular - 无法访问角材料内的元素
- r - 计算昨天收盘价的每日百分比变化并将其应用于多个代码的函数
- homebrew - Homebrew 的公式依赖性
- python - 如何使用 Python 编辑 XML 文件