为什么在 svg 中设置 xlink href 时 setAttribute/getAttribute 与参数不一致?
Why setAttribute/getAttribute is inconsistent with arguments when setting xlink href in svg?
为什么我们需要使用
element.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "link")
在图像上设置 href 时,但紧随其后
element.getAttributeNS("http://www.w3.org/1999/xlink", "xlink:href")
returns 无效?
相反,只能使用
检索属性
element.getAttributeNS("http://www.w3.org/1999/xlink", "href")
为什么在设置的时候要使用多余的"xlink:"前缀,而在获取属性值的时候却必须省略?
您似乎对命名空间元素和属性的工作方式感到困惑。
在内联标记中,您确实会向根元素添加一个 xmlns
属性,或者在您之后向命名空间属性(例如 xlink:
)添加一个命名空间 header已将其 namespaceURI 定义为根元素的属性。
这是浏览器能够理解这些是命名空间所必需的,否则,它将尝试使用文档的命名空间 URI 来解析它(默认情况下,"http://www.w3.org/1999/xhtml"
in html 文档)
但是,因为你处理的是javascript,这些namespaceURI需要在创建元素或属性时设置。
为此,您使用 document.createElementNS(namespaceURI, elementName)
, and element.setAttributeNS(namespaceURI, attrName, attrValue)
,甚至 document.createAttributeNS(...)
。
因为你已经在 js 中设置了它,并且浏览器不需要在标记中实际写入它,所以你不会看到 xmlns
属性,也不会看到 xlink:
NSheader 在你的检查器中,但他们在这里。
您可以调用元素的 outerHTML
属性 来说服自己,顺便说一句,获得 DOM 的字符串表示的更好方法是使用 XMLSerializer
并且它是 serializeToString(elem)
方法。
console.log("document's namespaceURI :",document.documentElement.namespaceURI)
// we're in an html document,
// this means that all 'createElement(xxx)' will correspond to
// 'document.createElementNS('http://www.w3.org/1999/xhtml', xxx)'
// our two namespace URIs
var svgNS = 'http://www.w3.org/2000/svg';
var xlinkNS = 'http://www.w3.org/1999/xlink';
// There is also an HTMLSVGElement
//but since you seem to want to make a standaone svg document from this node,
// you have to use the NS version
var svgRoot = document.createElementNS(svgNS, 'svg');
var a = document.createElementNS(svgNS, 'a');
// this is an xlink attribute
// note that you should not set the 'xlink:' header, the browser already know its namespace
a.setAttributeNS(xlinkNS, 'href', 'http://whosebug.com');
// an other SVG element
var r = document.createElementNS(svgNS, 'rect');
r.setAttribute('width', 50);
r.setAttribute('height', 50);
a.appendChild(r);
svgRoot.appendChild(a);
document.body.appendChild(svgRoot);
// here we see that the 'xlink:' header is actually set,
// but it forgets the namespace URI declarations in some UAs (at least in FF...).
console.log("outerHTML :", svgRoot.outerHTML);
// so better use an XMLSerializer :
console.log("serialized :", new XMLSerializer().serializeToString(svgRoot));
和getAttribute
的工作方式相同:non-NS版本将使用调用它的document
的命名空间。
现在,为什么你可以调用 setAttributeNS(nameSpaceURI, 'namespace:attr', val)
,但不能调用 getAttributeNS(nameSpaceURI, 'namespace:attr')`,这是因为在这种特殊情况下,浏览器足够友好地纠正你.
你可以看到调用 setAttribute('xlink:href', value)
将创建一个不同于 NS 版本设置的属性,并且使用 lambda header 设置 href 属性只会覆盖没有这个的属性header。在这里设置这个header的唯一原因是为了在将节点序列化为字符串时控制命名空间的名称;浏览器会有不同的默认值,但这个 xlink
名称只是一个约定,实际上可以是任何你想要的。
var svgNS = 'http://www.w3.org/2000/svg';
var xlinkNS = 'http://www.w3.org/1999/xlink';
var svgRoot = document.createElementNS(svgNS, 'svg');
var a = document.createElementNS(svgNS, 'a');
// browsers should keep it but don't set it as the actual link target
a.setAttribute('xlink:href', 'http://noHeader.com');
// same here
a.setAttribute('href', 'http://noNameSpace.com');
// this one is correct
a.setAttributeNS(xlinkNS, 'href', 'http://xlinkNoHeader.com');
// but this will overwrite the previous one without the header
a.setAttributeNS(xlinkNS, 'other:href', 'http://xlinkOtherHeader.com');
var r = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
r.setAttribute('width', 50);
r.setAttribute('height', 50);
a.appendChild(r);
svgRoot.appendChild(a);
document.body.appendChild(svgRoot);
for (var i = 0; i < a.attributes.length; i++) {
console.log(a.attributes[i].name, a.attributes[i].textContent, a.attributes[i].namespaceURI);
}
但是如果你在 Chrome 上尝试这个,你可能会看到实际保留的一个属性是没有命名空间的那个。这是一个错误。
为什么我们需要使用
element.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "link")
在图像上设置 href 时,但紧随其后
element.getAttributeNS("http://www.w3.org/1999/xlink", "xlink:href")
returns 无效?
相反,只能使用
检索属性element.getAttributeNS("http://www.w3.org/1999/xlink", "href")
为什么在设置的时候要使用多余的"xlink:"前缀,而在获取属性值的时候却必须省略?
您似乎对命名空间元素和属性的工作方式感到困惑。
在内联标记中,您确实会向根元素添加一个 xmlns
属性,或者在您之后向命名空间属性(例如 xlink:
)添加一个命名空间 header已将其 namespaceURI 定义为根元素的属性。
这是浏览器能够理解这些是命名空间所必需的,否则,它将尝试使用文档的命名空间 URI 来解析它(默认情况下,"http://www.w3.org/1999/xhtml"
in html 文档)
但是,因为你处理的是javascript,这些namespaceURI需要在创建元素或属性时设置。
为此,您使用 document.createElementNS(namespaceURI, elementName)
, and element.setAttributeNS(namespaceURI, attrName, attrValue)
,甚至 document.createAttributeNS(...)
。
因为你已经在 js 中设置了它,并且浏览器不需要在标记中实际写入它,所以你不会看到 xmlns
属性,也不会看到 xlink:
NSheader 在你的检查器中,但他们在这里。
您可以调用元素的 outerHTML
属性 来说服自己,顺便说一句,获得 DOM 的字符串表示的更好方法是使用 XMLSerializer
并且它是 serializeToString(elem)
方法。
console.log("document's namespaceURI :",document.documentElement.namespaceURI)
// we're in an html document,
// this means that all 'createElement(xxx)' will correspond to
// 'document.createElementNS('http://www.w3.org/1999/xhtml', xxx)'
// our two namespace URIs
var svgNS = 'http://www.w3.org/2000/svg';
var xlinkNS = 'http://www.w3.org/1999/xlink';
// There is also an HTMLSVGElement
//but since you seem to want to make a standaone svg document from this node,
// you have to use the NS version
var svgRoot = document.createElementNS(svgNS, 'svg');
var a = document.createElementNS(svgNS, 'a');
// this is an xlink attribute
// note that you should not set the 'xlink:' header, the browser already know its namespace
a.setAttributeNS(xlinkNS, 'href', 'http://whosebug.com');
// an other SVG element
var r = document.createElementNS(svgNS, 'rect');
r.setAttribute('width', 50);
r.setAttribute('height', 50);
a.appendChild(r);
svgRoot.appendChild(a);
document.body.appendChild(svgRoot);
// here we see that the 'xlink:' header is actually set,
// but it forgets the namespace URI declarations in some UAs (at least in FF...).
console.log("outerHTML :", svgRoot.outerHTML);
// so better use an XMLSerializer :
console.log("serialized :", new XMLSerializer().serializeToString(svgRoot));
和getAttribute
的工作方式相同:non-NS版本将使用调用它的document
的命名空间。
现在,为什么你可以调用 setAttributeNS(nameSpaceURI, 'namespace:attr', val)
,但不能调用 getAttributeNS(nameSpaceURI, 'namespace:attr')`,这是因为在这种特殊情况下,浏览器足够友好地纠正你.
你可以看到调用 setAttribute('xlink:href', value)
将创建一个不同于 NS 版本设置的属性,并且使用 lambda header 设置 href 属性只会覆盖没有这个的属性header。在这里设置这个header的唯一原因是为了在将节点序列化为字符串时控制命名空间的名称;浏览器会有不同的默认值,但这个 xlink
名称只是一个约定,实际上可以是任何你想要的。
var svgNS = 'http://www.w3.org/2000/svg';
var xlinkNS = 'http://www.w3.org/1999/xlink';
var svgRoot = document.createElementNS(svgNS, 'svg');
var a = document.createElementNS(svgNS, 'a');
// browsers should keep it but don't set it as the actual link target
a.setAttribute('xlink:href', 'http://noHeader.com');
// same here
a.setAttribute('href', 'http://noNameSpace.com');
// this one is correct
a.setAttributeNS(xlinkNS, 'href', 'http://xlinkNoHeader.com');
// but this will overwrite the previous one without the header
a.setAttributeNS(xlinkNS, 'other:href', 'http://xlinkOtherHeader.com');
var r = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
r.setAttribute('width', 50);
r.setAttribute('height', 50);
a.appendChild(r);
svgRoot.appendChild(a);
document.body.appendChild(svgRoot);
for (var i = 0; i < a.attributes.length; i++) {
console.log(a.attributes[i].name, a.attributes[i].textContent, a.attributes[i].namespaceURI);
}
但是如果你在 Chrome 上尝试这个,你可能会看到实际保留的一个属性是没有命名空间的那个。这是一个错误。