Можно ли использовать HTML.querySelector () для выбора атрибута xlink в 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() чтобы выбрать ссылку внутри SVG по содержанию его

3 ответов


селектор запроса can обрабатывать пространства имен, но это становится сложнее, потому что

  1. синтаксис для указания пространств имен в селекторах CSS отличается от html;

  2. API querySelector не имеет никакого метода для назначения префикса пространства имен (например,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/

API селекторов принимает синтаксис селектора CSS, но не имеет эквивалента @namespace правила для определения пространства имен. В результате селекторы с пространствами имен недопустимы но маркер пространства имен подстановочных знаков действителен:

если группа селекторов включает префиксы пространства имен, которые необходимо разрешить, реализация должна вызвать исключение SYNTAX_ERR ([DOM-LEVEL-3-CORE], раздел 1.4).

эта спецификация не поддерживает разрешение произвольных префиксов пространства имен. Однако можно рассмотреть возможность поддержки механизма разрешения префикса пространства имен для включения в будущую версию этой спецификации.

префикс пространства имен должен быть разрешен, если компонент пространства имен не пуст (например,|div), представляющий пространство имен null или звездочку (например,*|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, но это на самом деле очень проблемная ошибка (в означает, что вы никогда не можете выбрать элементы SVG со смешанными именами тегов).

но работает ли то же самое решение для xlink:href? Нет! Синтаксический анализатор HTML 5 распознает xlink:href в разметке SVG и правильно анализирует ее как атрибут пространства имен.

вот обновленная скрипка с дополнительными тестами. Опять же, посмотрите на вывод консоли на увидеть результаты. Протестировано в Chrome 40, Firefox 35 и IE 11; единственная разница в поведении заключается в том, что Chrome соответствует селектору смешанных регистров.


к сожалению, нет.

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();

Если вам нужна полная поддержка кросс-браузера, например, для IE, который не имеет document.evaluate, вы можете polyfill его с злой-хороший-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;

[*|href] будет соответствовать обоим html href и svg xlink:href, а затем использовать :not([href]) исключить html href.

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

протестировано в chrome