admin管理员组文章数量:1318563
It appears web browsers throw a DOMException
when one uses setAttributeNS
on a <svg>
element to set the xmlns
attribute. i.e.
>>> s = document.createElementNS('', 'svg')
<svg></svg>
>>> s.setAttributeNS(null, 'xmlns', '123')
Uncaught DOMException: Failed to execute 'setAttributeNS'
on 'Element': '' is an invalid namespace for attributes.
>>> s.setAttributeNS('', 'xmlns',
'')
Uncaught DOMException: Failed to execute 'setAttributeNS'
on 'Element': '' is an invalid namespace for attributes.
>>> s.setAttributeNS(null, 'xmlns', '')
Uncaught DOMException: Failed to execute 'setAttributeNS'
on 'Element': '' is an invalid namespace for attributes.
The Mozilla docs remend always using setAttributeNS
, however it makes no mention of this possibility. So the remendation appears to have caveats.
The DOM Level 2 spec on setAttributeNS
gives some insight:
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 "", or if the qualifiedName is "xmlns" and the namespaceURI is different from "/".
So this particular exception appears to be part of a broader set of cases that could fail. It's not immediately apparent what those cases are.
I'm writing tko / Knockout 4.0, a general-purpose web framework, and so it should support svg
and other tags outside the core HTML namespace.
The most encountered problem es from xmlns
on svg
tags so it's an issue. I've worked around this by specifically checking to see if xmlns
is being set and using setAttribute
in that case.
That workaround seems quite specific and I'm concerned about the general case. Is there a precedent for how to generally handle setting attributes with setAttributeNS
and setAttribute
?
The other web frameworks don't address this neatly — it's generally mixed with other logic; the most on-point mit I've seen is for angular, but it's not directly addressing this problem.
Related: Difference between setAttribute and setAttributeNS(null,
It appears web browsers throw a DOMException
when one uses setAttributeNS
on a <svg>
element to set the xmlns
attribute. i.e.
>>> s = document.createElementNS('http://www.w3/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/2000/svg', 'xmlns',
'http://www.w3/2000/svg')
Uncaught DOMException: Failed to execute 'setAttributeNS'
on 'Element': '' is an invalid namespace for attributes.
>>> s.setAttributeNS(null, 'xmlns', 'http://www.w3/2000/svg')
Uncaught DOMException: Failed to execute 'setAttributeNS'
on 'Element': '' is an invalid namespace for attributes.
The Mozilla docs remend always using setAttributeNS
, however it makes no mention of this possibility. So the remendation appears to have caveats.
The DOM Level 2 spec on setAttributeNS
gives some insight:
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/XML/1998/namespace", or if the qualifiedName is "xmlns" and the namespaceURI is different from "http://www.w3/2000/xmlns/".
So this particular exception appears to be part of a broader set of cases that could fail. It's not immediately apparent what those cases are.
I'm writing tko / Knockout 4.0, a general-purpose web framework, and so it should support svg
and other tags outside the core HTML namespace.
The most encountered problem es from xmlns
on svg
tags so it's an issue. I've worked around this by specifically checking to see if xmlns
is being set and using setAttribute
in that case.
That workaround seems quite specific and I'm concerned about the general case. Is there a precedent for how to generally handle setting attributes with setAttributeNS
and setAttribute
?
The other web frameworks don't address this neatly — it's generally mixed with other logic; the most on-point mit I've seen is for angular, but it's not directly addressing this problem.
Related: Difference between setAttribute and setAttributeNS(null,
Share Improve this question edited Sep 29, 2018 at 19:07 Brian M. Hunt asked Sep 29, 2018 at 18:06 Brian M. HuntBrian M. Hunt 83.9k76 gold badges234 silver badges349 bronze badges 8-
When I create an SVG I use
var svg = document.createElementNS(ns.svg, "svg");
wherens.svg: "http://www.w3/2000/svg"
– enxaneta Commented Sep 29, 2018 at 18:37 -
Wouldn't it be better to force pliance to the spec and set the
xmlns
namespaceURI if it's encountered - and, for the same reason, set thexml
namespaceURI if it has been used as a prefix? – ccprog Commented Sep 29, 2018 at 18:43 -
@ccprog TKO does indeed set the
xmlns
according to the spec, and that is the better approach, but that does not solve the problem. – Brian M. Hunt Commented Sep 29, 2018 at 18:45 -
i.e.
document.createElementNS('http://www.w3/2000/svg', "svg").setAttributeNS(null, 'xmlns', '...')
throws – Brian M. Hunt Commented Sep 29, 2018 at 18:46 -
What I meant was, in the method you quoted, something like
var ns = name === 'xmlns' ? 'http://www.w3/2000/xmlns/' : null;
node.setAttributeNS(ns, name, String(value))
– ccprog Commented Sep 29, 2018 at 18:51
1 Answer
Reset to default 7It will not cover all cases, but this should go a long way:
const NAMESPACES = {
svg: 'http://www.w3/2000/svg',
html: 'http://www.w3/1999/xhtml',
xml: 'http://www.w3/XML/1998/namespace',
xlink: 'http://www.w3/1999/xlink',
xmlns: 'http://www.w3/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))
}
}
}
If the attribute encountered is xmlns="http://www.w3/2000/svg"
, it will be added with
.setAttributeNS('http://www.w3/2000/xmlns/', 'xmlns', 'http://www.w3/2000/svg')
If the attribute encountered is xml:space="preserve"
(something that SVG editors notoriously use), it will be added with
.setAttributeNS('http://www.w3/XML/1998/namespace', 'xml:space', 'preserve')
本文标签: javascriptsetAttributeNS xmlns of ltsvggt for a generalpurpose libraryStack Overflow
版权声明:本文标题:javascript - setAttributeNS xmlns of <svg> for a general-purpose library - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1742049157a2417969.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论