在svg中设置xlink href时,为什么setAttribute / getAttribute与参数不一致?

时间:2016-06-10 10:41:13

标签: javascript svg attributes xml-namespaces

为什么我们需要使用

element.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", "link")

在图像上设置href,但在此之后

element.getAttributeNS("http://www.w3.org/1999/xlink", "xlink:href")

返回null?

相反,只能使用

检索属性
element.getAttributeNS("http://www.w3.org/1999/xlink", "href")

为什么我们在设置时应该使用冗余的“xlink:”前缀,但在获取属性值时必须省略它?

1 个答案:

答案 0 :(得分:3)

您似乎对命名空间元素和属性的工作方式感到困惑。

在您的内联标记中,您确实在根元素之后添加了xmlns属性,或者在您之后添加了命名空间属性(例如xlink:)的命名空间标题将其namespaceURI定义为根元素的属性 这对于浏览器能够理解这些是命名空间是必要的,否则,它将尝试使用文档的namespaceURI(默认情况下,在html文档中"http://www.w3.org/1999/xhtml")解析它。

但是,因为您正在处理javascript,所以需要在创建元素或属性时设置这些namespaceURI。
为此,您使用document.createElementNS(namespaceURI, elementName)element.setAttributeNS(namespaceURI, attrName, attrValue),甚至document.createAttributeNS(...)

因为您已经在js中设置了它,并且浏览器不需要在标记中实际写入它,所以您不会看到xmlns属性也不会{{1检查员中的NSheader,但他们就在这里。

您可以调用元素的xlink:属性来说服自己,顺便说一句,获取DOM的字符串表示形式的更好方法是使用XMLSerializer并使用{{3}} outerHTML方法。



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://stackoverflow.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));的工作方式相同:非NS版本将使用调用它的getAttribute命名空间。

现在,为什么你可以调用document,但不能调用getAttributeNS(nameSpaceURI,' namespace:attr')`,因为浏览器很友好在这种特殊情况下,足以纠正你。

您可以看到调用setAttributeNS(nameSpaceURI, 'namespace:attr', val)将创建除NS版本设置的属性之外的其他属性,并且设置带有lambda标头的href属性只会覆盖没有此标头的属性。在此处设置此标头的唯一原因是在将节点序列化为字符串时控制命名空间的名称;浏览器将具有不同的默认值,但此setAttribute('xlink:href', value)名称只是一个约定,它实际上可以是您想要的任何内容。



xlink




但是如果您在Chrome上尝试此操作,您可能会发现实际保留的一个属性是没有命名空间的属性。这是一个错误。