【问题标题】:namespace attributes not present in .outerHTML.outerHTML 中不存在命名空间属性
【发布时间】:2020-07-11 19:09:31
【问题描述】:

在 HTML5/JavaScript 中,如果我以编程方式创建命名空间的 dom 节点,如下所示:

svgElt = document.createElementNS("http://www.w3.org/2000/svg", 'svg')

节点“知道”它是自己的命名空间,我可以像这样检索它:

svgElt.namespaceURI // result: "http://www.w3.org/2000/svg"

但命名空间不被视为“正常”属性:

svgElt.getAttribute('xmlns') // result: null

所以以编程方式创建的节点的行为不同于等效的“直”节点

<svg xmlns="http://www.w3.org/2000/svg" id="mySVG"></svg>

.getAttribute 适用于:

document.getElementById('mySVG').getAttribute('xmlns') // result: "http://www.w3.org/2000/svg"

当我使用.outerHTML 并且需要结果中包含的命名空间信息时,这是一个潜在的问题。以编程方式创建的节点的命名空间信息可能会丢失,我可能必须手动添加它;这似乎是“我不应该关心”的事情——这就是问题所在。

当您想通过将图像源设置为数据地址,如

'data:image/svg+xml,' + your_svg_element.outerHTML

我做的是

svgNode.setAttribute('xmlns', svgNode.namespaceURI)

SVG -> 图像转换(正如我实现的那样)没有这个技巧就无法工作;另请参阅我对上面链接的问题的回答。

有没有更好/更优雅的方法来做到这一点? svgElt.getAttribute('xmlns') 返回null 的目的是什么?缺陷或功能?

【问题讨论】:

  • 我说的是文档的mime类型
  • @RobertLongson:当然。所以你是说,如果我改变了我提供文档的 mime 类型,在某个 dom 节点上调用 .outerHTML 的结果会改变,我理解正确吗?
  • @mathheadinclouds - 是的,它可以做到。提供给它们的 MIME 类型会导致正在构建的 HTML 文档或 XML 文档。您还可以在 JavaScript 中创建任一类型的文档。读取 .outerHTML 因文档类型而异。 difference between the algorithms for both types is described in the DOM Parsing and Serialization spec.
  • FWIW,您描述的属性和 namespaceUri 分离问题可以追溯到 DOM 起源时做出的妥协,并且一直是挫折和困惑的根源。其他解决此问题的对象模型 API 和一些类似问题已在其他地方尝试和使用,但对于浏览器中的 JS,DOM 经久不衰。向后兼容性限制意味着必须保留古怪的行为。

标签: javascript svg dom namespaces xhtml


【解决方案1】:

您可以简单地为此使用XMLSerializer,这会将您的 DOM 树字符串化为 xml,从而保留命名空间。

const svgElt = document.createElementNS("http://www.w3.org/2000/svg", 'svg')
const serialized = new XMLSerializer().serializeToString(svgElt);
console.log(serialized);

【讨论】:

    【解决方案2】:

    请先阅读问题中的cmets。

    以下是我们如何通过“xhtml-ifying”dom 节点,然后调用 .outerHTML 来获取带有命名空间信息的 html,这将是 xhtml(并具有 html 缺少的命名空间信息)。

    function outerXHTML(node){
        var nsx = "http://www.w3.org/1999/xhtml";
        var xdoc = document.implementation.createDocument(nsx, 'html');
        xdoc.documentElement.appendChild(node);
        return node.outerHTML;
    }
    function innerXHTML(node){
        var nsx = "http://www.w3.org/1999/xhtml";
        var xdoc = document.implementation.createDocument(nsx, 'html');
        xdoc.documentElement.appendChild(node);
        return node.innerHTML;
    }
    

    (如果应该保留在原始文档中,请先克隆节点。)

    related question (x/html conversion)

    related question (document creation)

    fiddle for testing the html to xhtml conversion

    test Kaiido version with arbitrary HTML string from textbox

    【讨论】:

      猜你喜欢
      • 2017-03-07
      • 2017-07-13
      • 2013-03-02
      • 2011-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-26
      • 1970-01-01
      相关资源
      最近更新 更多