こちらの記事(#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>