繁体   English   中英

是否可以使用 HTML 的 .querySelector() 在 SVG 中通过 xlink 属性进行选择?

[英]Is it possible to use HTML's .querySelector() to select by xlink attribute in an SVG?

鉴于:

<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

有没有办法编写该属性选择器以使其“看到” xlink:href

查询选择器可以处理命名空间,但它变得棘手,因为

  1. 在 CSS 选择器中指定命名空间的语法与 html 不同;

  2. querySelector API 没有任何方法可以将命名空间前缀(如xlink )分配给实际命名空间(如"http://www.w3.org/1999/xlink" )。

首先,CSS 规范的相关部分允许您指定命名空间(默认)、特定命名空间或任何命名空间:

 @namespace foo "http://www.example.com"; [foo|att=val] { color: blue } [*|att] { color: yellow } [|att] { color: green } [att] { color: green }

第一条规则将只匹配与属性元素att在“ http://www.example.com值为“VAL””命名空间。

第二条规则将只匹配具有属性att元素,而不管属性的命名空间(包括无命名空间)。

最后两条规则是等价的,并且只匹配属性不在命名空间中的属性为att元素。

请参阅此小提琴,注意填充样式(默认、悬停和活动):
https://jsfiddle.net/eg43L/

Selectors API 采用 CSS 选择器语法,但没有与用于定义命名空间的@namespace规则等效的规则。 因此, 具有命名空间的选择器无效,通配符命名空间标记有效

如果选择器组包含需要解析的命名空间前缀,则实现必须引发 SYNTAX_ERR 异常([DOM-LEVEL-3-CORE],第 1.4 节)。

本规范不支持解析任意命名空间前缀。 但是,可能会考虑在本规范的未来版本中包含对名称空间前缀解析机制的支持。

如果名称空间组件既不是空的(例如|div ),代表空名称空间,也不是星号(例如*|div ),代表任何名称空间,则需要解析名称空间前缀。 由于不需要解析星号或空名称空间前缀,因此选择器中支持名称空间语法的实现必须支持这些。

(加粗)

再次检查小提琴,这次注意控制台输出。 命令document.querySelector('[*|href="#url"]')返回您想要的元素。

最后一个警告: MDN告诉我 IE8- 不支持 CSS 命名空间,所以这可能对他们不起作用。


2015-01-31 更新:

正如@Netsi1964 在评论中指出的那样,这不适用于 HTML 5 文档中的自定义命名空间属性,因为 HTML 不支持 XML 命名空间。 (它可以在独立的 SVG 或其他 XML 文档(包括 XHTML)中工作。)

当 HTML5 解析器遇到类似data:myAttribute="value"的属性时,它会将其视为属性名称的单个字符串,包括: 为了让事情更加混乱,它会自动小写字符串。

要让querySelector选择这些属性,您必须包含data:作为属性字符串的一部分。 但是,由于:在 CSS 选择器中具有特殊含义,因此您需要使用\\字符对其进行转义。 既然你需要的\\打通传递作为选择的一部分,你需要逃避在你的JavaScript。

因此,成功的调用看起来像:

document.querySelector('[data\\:myattribute="value"]');

为了使事情更合乎逻辑,我建议对属性名称使用全部小写,因为 HTML 5 解析器无论如何都会转换它们。 Blink/Webkit 浏览器会自动将您传递给querySelector选择器querySelector小写,但这实际上是一个非常有问题的错误(这意味着您永远无法选择带有混合大小写标签名称的 SVG 元素)。

但是相同的解决方案是否适用于xlink:href 不! HTML 5 解析器识别 SVG 标记中的xlink:href ,并将其正确解析为命名空间属性。

这是带有附加测试的更新小提琴 再次查看控制台输出以查看结果。 在 Chrome 40、Firefox 35 和 IE 11 中测试; 行为的唯一区别是 Chrome 匹配大小写混合选择器。

[*|href]将匹配 html href和 svg xlink:href ,然后使用:not([href])排除 html href

document.querySelectorAll('[*|href]:not([href])')

在铬中测试

不幸的是没有。

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 对其进行 polyfill

当然,根据您的使用情况,这样做可能更容易(我认为这适用于 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;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM