【JavaScript】XPathを使用する#1 ノードセット編

XMLの読込みとXSL変換できたので、IE⇒Edge対応はこれにて一件落着と思ったら、XPathを使用しているところがありました。

ひろぴよ
ひろぴよ

当然動かない…


XPathの適用SelectNodesメソッドを使用していたのですが、XMLの読込みをXMLHttpRequestに変更したためか、SelectNodesメソッドが使えなくなっていました。
ということで、こちらも改修したので方法をまとめます。

テストデータ

いろいろと調べたところdocument.evaluateメソッドが使えました。
とりあえずサンプルコードです。

使用するXMLは次の通りです。
※ファイル名はplayer.xml

<?xml version="1.0" encoding="utf-8" ?>
<team>
  <name>オリックス・バッファローズ</name>
  <players>
    <player>
      <position>投手</position>
      <name>yamamoto</name>
    </player>
    <player>
      <position>投手</position>
      <name>miyagi</name>
    </player>
    <player>
      <position>内野手</position>
      <name>okada</name>
    </player>    
    <player>
      <position>内野手</position>
      <name>adachi</name>
    </player>
    <player>
      <position>内野手</position>
      <name>mune</name>
    </player>
    <player>
      <position>内野手</position>
      <name>kurebayashi</name>
    </player>
    <player>
      <position>外野手</position>
      <name>yoshida</name>
    </player>
    <player>
      <position>外野手</position>
      <name>sugimoto</name>
    </player>
    <player>
      <position>外野手</position>
      <name>fukuda</name>
    </player>
  </players>
</team>

サンプルコード

続いてHTMLとJavaScriptです。
上記のXMLと併せてWebサーバー上に保管して表示させてください。
ローカル環境だと動作しないので注意です。
35行目でdocument.evaluateメソッドを使用しています。
今回のコードではXMLから外野手をXPathを適用して抽出しています。
※自作関数は、関数名を「my_」から始めてあります
※Edge、Google Chromeで動作確認済

<!DOCTYPE html>

<html>
    <head>
        <script>
            // onload時に実行
            function my_onLoad(){

                const objXml = my_loadXML('./player.xml');

                let outfielder_list = my_getPlayer(objXml, '外野手');

                document.write('<h3>外野手一覧</h3>');
                for (let i=0; i<outfielder_list.length; i++){
                    document.write(outfielder_list[i] + '<br>');
                }
            }

            // XMLを読み込む
            // path : 読み込むXMLのパス
            function my_loadXML(path){
                let objXml = new XMLHttpRequest();
                objXml.open('GET', path, false);
                objXml.send('');
                return objXml.responseXML;
            }

            // positionで指定した選手を配列で返す
            function my_getPlayer(objXml, position) {

                // XPathを作成
                let xPath = "//player/name[../position='" + position + "']";

                // XPathを適用
                let result = objXml.evaluate(xPath, objXml, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);

                // XPathを適用した結果を配列に保存
                let result_list = new Array();
                let r;
                while (r = result.iterateNext()) {
                    result_list.push(r.textContent);
                }
                return result_list;
            }
        </script>
    </head>
    <body onload='my_onLoad()'>
    </body>
</html>

実際に実行すると、下記の様に表示されます。

document.evaluateメソッドの構文と引数

var resultNode = document.evaluate(
  xpathExpression,
  contextNode,
  namespaceResolver,
  resultType,
  result
);
引数名説明
xpathExpression ※必須XPath
contextNode ※必須XPathを適用するノード
namespaceResolver任意の名前空間接頭辞 ※nullでよさそう
returnTypeXPathを適用した戻り値の種類を指定
result既存の XPathResult  ※nullでよさそう

returnType(戻り値の種類)で設定できる値

定数説明
ANY_TYPE0戻り値を自動判別
NUMBER_TYPE1数値、count()などで使用
STRING_TYPE2文字列
BOOLEAN_TYPE3ブール値
UNORDERED_NODE_ITERATOR_TYPE4ノードセット
ドキュメントと順序が異なることがある
ドキュメントを変更すると、イテレーションが無効になる
ORDERED_NODE_ITERATOR_TYPE5ドキュメント順のノードセット
ドキュメントを変更すると、イテレーションが無効になります
UNORDERED_NODE_SNAPSHOT_TYPE6ノードのスナップショット
ドキュメントと順序が異なることがある
ORDERED_NODE_SNAPSHOT_TYPE7ドキュメント順のノードのスナップショット
ANY_UNORDERED_NODE_TYPE8XPathに一致する単一のノード
※最初のノードとは限らない
FIRST_ORDERED_NODE_TYPE9XPathに一致する最初のノード
ドキュメントとは

XPathを適用するXMLのことです

イテレーションとは

反復処理のことです

引数で指定するときは

XPathResult.ORDERED_NODE_ITERATOR_TYPEの様に、頭にXPathResultを付けてください

個人的にですが、よく使いそうなのはノードセットスナップショットな気がします。
今回はノードセット(ORDERED_NODE_ITERATOR_TYPE)を使用しました。
スナップショット(ORDERED_NODE_SNAPSHOT_TYPE)を使用する方法はこちら
※ノードセットとスナップショットでは結果の取り出し方が違います

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA