假设:
<body>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<a xlink:href="url"></a>
</svg>
</body>
是否可以使用HTML DOM .querySelector()
或.querySelectorAll()
通过其xlink:href
属性的内容选择SVG内的链接?
这有效:
document.querySelector('a') // <a xlink:href="url"/>
这些不是:
document.querySelector('[href="url"]') // null
document.querySelector('[xlink:href="url"]') // Error: not a valid selector
document.querySelector('[xlink\:href="url"]') // Error: not a valid selector
document.querySelector('[xlink\\:href="url"]') // null
是否有办法编写该属性选择器以使其“看到&#39; xlink:href
?
答案 0 :(得分:39)
查询选择器可以处理名称空间,但是因为
而变得棘手在CSS选择器中指定名称空间的语法与html不同;
querySelector API没有任何方法可以将名称空间前缀(如xlink
)分配给实际名称空间(如"http://www.w3.org/1999/xlink"
)。
在第一点上,the relevant part of the CSS specs允许您指定 no 命名空间(默认),特定命名空间或任何命名空间:
@namespace foo "http://www.example.com"; [foo|att=val] { color: blue } [*|att] { color: yellow } [|att] { color: green } [att] { color: green }
第一条规则只匹配&#34; http://www.example.com&#34;中的属性
att
的元素。名称空间的值为&#34; val&#34;。第二条规则将仅匹配具有属性
att
的元素,而不管属性的名称空间(包括没有名称空间)。最后两条规则是等效的,只会匹配属性为
att
的元素,其中属性不是在命名空间中。
请注意这个小提琴,注意填充样式(默认,悬停和活动):
https://jsfiddle.net/eg43L/
Selectors API采用CSS选择器语法,但没有用于定义命名空间的@namespace
规则。因此,selectors with namespaces are not valid but the wildcard namespace token is valid:
如果选择器组包含需要解析的名称空间前缀,则实现必须引发SYNTAX_ERR异常([DOM-LEVEL-3-CORE],第1.4节)。
此规范不支持解析任意名称空间前缀。但是,可以考虑支持名称空间前缀解析机制以包含在本规范的未来版本中。
如果命名空间组件既不是空的(例如
|div
),表示空命名空间,也不是星号(例如*|div
),代表任何命名空间,则需要解析名称空间前缀。 由于不需要解析星号或空名称空间前缀,因此在选择器中支持名称空间语法的实现必须支持这些。
(加粗)
再次查看the fiddle,这次要注意控制台输出。命令document.querySelector('[*|href="#url"]')
返回您想要的元素。
最后一个警告:MDN告诉我IE8-不支持CSS名称空间,所以这可能不适合他们。
更新2015-01-31:
正如@ Netsi1964在评论中指出的那样,这对于HTML 5文档中的自定义命名空间属性不起作用,因为HTML不支持XML命名空间。 (它可以在独立的SVG或包含XHTML的其他XML文档中工作。)
当HTML5解析器遇到类似data:myAttribute="value"
的属性时,它会将其视为属性名称的单个字符串,包括:
。为了让事情更加混乱,它会自动缩小字符串。
要让querySelector
选择这些属性,您必须将data:
作为属性字符串的一部分。但是,由于:
在CSS选择器中具有特殊含义,因此需要使用\
字符对其进行转义。因为您需要\
作为选择器的一部分传递,所以您需要在JavaScript中转义 it 。
因此成功的通话如下:
document.querySelector('[data\\:myattribute="value"]');
为了使事情更合理,我建议使用所有小写字母作为属性名称,因为HTML 5解析器无论如何都会转换它们。 Blink / Webkit浏览器将自动小写您传递querySelector
的选择器,但这实际上是一个非常有问题的错误(意味着您永远不能选择具有混合大小写标记名称的SVG元素)。
但同样的解决方案适用于xlink:href
吗?没有! HTML 5解析器识别SVG标记中的xlink:href
,并正确地将其解析为命名空间属性。
Here's the updated fiddle with additional tests。再次,查看控制台输出以查看结果。在Chrome 40,Firefox 35和IE 11中测试过;行为的唯一区别是Chrome与混合大小写选择器匹配。
答案 1 :(得分:6)
不幸的是没有。
querySelector
不处理XML命名空间,因此没有简单的方法可以这样做。但是,您可以使用XPath
查询。
var result = document.evaluate(
// Search for all nodes with an href attribute in the xlink namespace.
'//*[@xlink:href="url"]',
document,
function(prefix){
return {
xlink: "http://www.w3.org/1999/xlink"
}[prefix] || null;
},
XPathResult.ORDERED_NODE_ITERATOR_TYPE
);
var element = result.iterateNext();
如果您需要完整的跨浏览器支持,例如对于没有document.evaluate
的IE,您可以使用wicked-good-xpath对其进行填充。
当然,根据您的使用情况,可能更容易做到这一点(我认为这适用于IE):
var element = Array.prototype.filter.call(document.querySelectorAll('a'),
function(el){
return el.getAttributeNS('http://www.w3.org/1999/xlink', 'href') === 'url';
})[0] || null;
答案 2 :(得分:4)
[*|href]
将匹配html href
和svg xlink:href
,然后使用:not([href])
排除html href
。
document.querySelectorAll('[*|href]:not([href])')
在chrome中测试