javascript - 通用库的 <svg> 的 setAttributeNS xmlns

标签 javascript xml dom svg

网络浏览器似乎抛出 DOMException当一个人使用setAttributeNS时在<svg>上元素设置 xmlns属性。即

>>> s = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
<svg>​</svg>​

>>> s.setAttributeNS(null, 'xmlns', '123')
Uncaught DOMException: Failed to execute 'setAttributeNS' 
  on 'Element': '' is an invalid namespace for attributes.

>>> s.setAttributeNS('http://www.w3.org/2000/svg', 'xmlns', 
      'http://www.w3.org/2000/svg')
Uncaught DOMException: Failed to execute 'setAttributeNS' 
  on 'Element': '' is an invalid namespace for attributes.

>>> s.setAttributeNS(null, 'xmlns', 'http://www.w3.org/2000/svg')
Uncaught DOMException: Failed to execute 'setAttributeNS' 
  on 'Element': '' is an invalid namespace for attributes.

Mozilla docs建议始终使用setAttributeNS ,但它没有提到这种可能性。因此,该建议似乎有一些警告。

DOM Level 2 specsetAttributeNS提供一些见解:

NAMESPACE_ERR: Raised if the qualifiedName is malformed, if the qualifiedName has a prefix and the namespaceURI is null, if the qualifiedName has a prefix that is "xml" and the namespaceURI is different from "http://www.w3.org/XML/1998/namespace", or if the qualifiedName is "xmlns" and the namespaceURI is different from "http://www.w3.org/2000/xmlns/".

因此,这个特殊的异常似乎是更广泛的可能失败的案例的一部分。目前尚不清楚这些案件是什么。

我正在编写 tko/Knockout 4.0,一个通用的 Web 框架,因此它应该支持 svg以及核心 HTML 命名空间之外的其他标记。

遇到最多的问题来自xmlnssvg标签,所以它是 an issue 。我有worked around this通过专门检查是否 xmlns正在设置并使用setAttribute在这种情况下。

该解决方法似乎非常具体,我担心一般情况。是否有先例说明如何通常使用 setAttributeNS 处理设置属性和setAttribute

其他 Web 框架并没有很好地解决这个问题——它通常与其他逻辑混合在一起;我见过的最准确的提交是 angular ,但它并没有直接解决这个问题。

相关:Difference between setAttribute and setAttributeNS(null,

最佳答案

它不会涵盖所有情况,但这应该会大有帮助:

const NAMESPACES = {
  svg: 'http://www.w3.org/2000/svg',
  html: 'http://www.w3.org/1999/xhtml',
  xml: 'http://www.w3.org/XML/1998/namespace',
  xlink: 'http://www.w3.org/1999/xlink',
  xmlns: 'http://www.w3.org/2000/xmlns/' // sic for the final slash...
}

class JsxObserver extends LifeCycle {
  ...

  setNodeAttribute (node, name, valueOrObservable) {
    const value = unwrap(valueOrObservable)
    NativeProvider.addValueToNode(node, name, valueOrObservable)
    if (value === undefined) {
      node.removeAttributeNS(null, name)
    } else if (isThenable(valueOrObservable)) {
      Promise.resolve(valueOrObservable)
        .then(v => this.setNodeAttribute(node, name, v))
    } else {
      const [prefix, ...unqualifiedName] = name.split(':')
      let ns = null
      if (prefix === 'xmlns' || unqualifiedName.length && NAMESPACES[prefix]) {
        ns = NAMESPACES[prefix]
      }
      node.setAttributeNS(ns, name, String(value))
    }
  }
}

如果遇到的属性是xmlns="http://www.w3.org/2000/svg",则会添加

.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'http://www.w3.org/2000/svg')

如果遇到的属性是 xml:space="preserve" (SVG 编辑器经常使用的属性),则会添加该属性

.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve')

关于javascript - 通用库的 <svg> 的 setAttributeNS xmlns,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52571125/

相关文章:

xml - 在内部,Postgres 如何存储 XML 数据?

javascript - 使用 JavaScript 或 Jquery 动态删除 html 输入字段

javascript - JS 与弹出联系表单冲突

javascript - 更新 URL 而不触发状态更改

javascript - Angularjs按钮根据页面具有不同的功能

java - 如何从标签中删除 namespace 但保留其前缀?

javascript - 如何反射(reflect)JStree对原始XML的更改?

javascript - 如何找到距给定坐标最近的点

javascript - 如何在 Javascript 中获取对象在页面上的绝对位置?

javascript - 显示 DOM 对象内容