【JavaScript】XPathを使用する#2 スナップショット編

こちらの記事(#1)の最後に書いてある通り、document.evaluateメソッドを用いてXPathの適用を行う際に、戻り値の種類が指定できます。今回は戻り値の種類にスナップショット(ORDERED_NODE_SNAPSHOT_TYPE)を指定してXPathを適用した結果を取り出してみます。

テストデータ

使用するXMLは#1と同じものを使用します。
※ファイル名は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サーバー上に保管して表示させてください。
※ローカル環境だと動作しないので注意
#1と同様に、XMLから外野手をXPathを適用して抽出しています。
35行目~41行目が#1と違う部分になります。
※自作関数は、関数名を「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_SNAPSHOT_TYPE, null);

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

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

結果の取り出し方の違い

ノートセット(ORDERED_NODE_ITERATOR_TYPE)での取り出し方です。
iterateNextメソッドで次のノードに対象を移します。

// 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);
}

続いて、スナップショット(ORDERED_NODE_SNAPSHOT_TYPE)での取り出し方です。
snapshotItemメソッドでインデックスを指定して対象を指定できます。
また、snapshotLengthプロパティで結果の数が確認できます。

// XPathを適用(戻り値はスナップショット)
let result = objXml.evaluate(xPath, objXml, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

// XPathを適用した結果を配列に保存
let result_list = new Array();
for(let i=0; i<result.snapshotLength; i++){
    result_list.push(result.snapshotItem(i).textContent);    
}

ちなみに両方で共通しているtextContentはノード内のテキストを取得します。
コード例のXPath、”//player/name[../position=’外野手’]”では、<name>を抽出しているので、<name>内のテキストを取得します。
例えば、<name>yoshida</name>の場合は、「yoshida」が取得されます。

XPathを”//player[./position=’外野手’] ”のように<palyer>を抽出するようにして、textContentを使うと<palyer>内の全てのテキストを取得してしまうので注意です。
例えば、次の場合は「外野手yoshida」が取得されます。

<player>
    <position>外野手</position>
    <name>yoshida</name>
</player>

コメントを残す

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

CAPTCHA