web-dev-qa-db-ja.com

HTMLの.querySelector()を使用してSVGのxlink属性で選択することは可能ですか?

与えられた:

_<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()を使用して、SV内のリンクを_xlink:href_属性の内容で選択することはできますか?

これは機能します:

_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_を「見る」ようにする方法はありますか?

37
stephband

クエリセレクターcanは名前空間を処理しますが、トリッキーになります。

  1. CSSセレクターで名前空間を指定するための構文は、htmlとは異なります。

  2. QuerySelector APIには、名前空間接頭辞(xlinkなど)を実際の名前空間(_"http://www.w3.org/1999/xlink"_など)に割り当てるメソッドはありません。

最初の点で、 CSS仕様の関連部分 を使用すると、no名前空間(デフォルト)、特定の名前空間、またはany名前空間:

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

最初のルールは、 " http://www.example.com "名前空間の属性attの値が「val」の要素のみに一致します。

2番目のルールは、属性の名前空間(名前空間なしを含む)に関係なく、属性attを持つ要素のみに一致します。

最後の2つのルールは同等であり、名前空間で属性がnotである属性attを持つ要素のみに一致します。

塗りつぶしのスタイル(デフォルト、ホバー、アクティブ)に注意して、このフィドルを参照してください。
https://jsfiddle.net/eg43L/

Selectors APIはCSSセレクター構文を採用していますが、名前空間を定義するための_@namespace_ルールに相当するものはありません。その結果、 名前空間を持つセレクターは無効ですワイルドカード名前空間トークンは有効です

セレクターのグループに解決が必要な名前空間プレフィックスが含まれている場合、実装はSYNTAX_ERR例外を発生させる必要があります([DOM-LEVEL-3-CORE]、セクション1.4)。

この仕様は、任意の名前空間接頭辞の解決をサポートしていません。ただし、名前空間接頭辞解決メカニズムのサポートは、この仕様の将来のバージョンに含めることを検討する可能性があります。

ネームスペースコンポーネントが空(例:_|div_)であり、nullネームスペースを表すか、アスタリスク(例:_*|div_)でネームスペースを表す場合、ネームスペースプレフィックスを解決する必要があります。 アスタリスクまたは空の名前空間接頭辞を解決する必要がないため、セレクターで名前空間構文をサポートする実装は、これらをサポートする必要があります。

(太字追加)

フィドル をもう一度確認してください。今回はコンソールの出力に注目しています。コマンドdocument.querySelector('[*|href="#url"]')は、必要な要素を返します。

最後の警告: [〜#〜] mdn [〜#〜] は、IE8-がCSS名前空間をサポートしていないため、これが機能しない可能性があることを示しています。


2015年1月31日更新:

@ Netsi1964がコメントで指摘したように、HTMLはXML名前空間をサポートしていないため、これはHTML 5ドキュメントのカスタム名前空間属性に対しては機能しません。 (スタンドアロンのSVGまたはXHTMLを含む他のXMLドキュメントで機能します。)

HTML5パーサーは、_data:myAttribute="value"_などの属性を検出すると、その属性を_:_を含む属性名の単一の文字列として扱います。混乱を招くため、文字列を自動的に小文字にします。

これらの属性を選択するためにquerySelectorを取得するには、属性文字列の一部として_data:_を含める必要があります。ただし、_:_はCSSセレクターで特別な意味を持つため、_\_文字でエスケープする必要があります。そして、セレクターの一部として渡されるには_\_が必要なので、JavaScriptでitをエスケープする必要があります。

したがって、成功した呼び出しは次のようになります。

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

少し論理的にするために、属性名にはすべて小文字を使用することをお勧めします。HTML5パーサーがとにかく変換​​するからです。 Blink/WebkitブラウザーはquerySelectorを渡すと自動的に小文字のセレクターになりますが、これは実際には非常に問題の多いバグです(つまり、大文字と小文字が混在するタグ名を持つSVG要素を選択することはできません)。

しかし、同じソリューションは_xlink:href_でも機能しますか?番号! HTML 5パーサーは、SVGマークアップ内の_xlink:href_を認識し、名前空間属性として正しく解析します。

これは、追加のテストを含む更新されたフィドルです 。もう一度、コンソールの出力を見て結果を確認します。 Chrome 40、Firefox 35、およびIE 11でテストされています。動作の唯一の違いは、Chrome -ケースセレクター。

44
AmeliaBR

_[*|href]_はhtml hrefとsvg _xlink:href_の両方に一致し、次に:not([href])を使用してhtml hrefを除外します。

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

クロムでテスト

7
cuixiping

残念ながら違います。

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がない完全なブラウザー間サポートが必要な場合は、 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;
6
loganfsmyth