javascript - 为什么一个 DOM 元素最多可以有两个相同的命名空间声明?

标签 javascript html xml svg xml-namespaces

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/

相关文章:

javascript - 如何在javascript中显示消息3秒

javascript - mySQL TIMEDIFF 查询 JS var - 由于冒号而出错

sql-server - 如何在 SQL XML 中使用 CDATA

android - Gridview教程问题

iphone - 如何使用 NSXMLParser 解析基本 XML 文件?

javascript - 基本 Javascript 变量作用域

javascript - 在 iframe 中隐藏导航栏和标题

php - 自动检测链接并将它们放入 <a> 标记中,除非它们已经在 html 标记中

javascript - 如何只绘制这部分圆弧?

javascript - 获取触发事件的元素(节点)