XPath は XML 文書の一部を指し示すための言語であり、W3C 勧告です。
この記事では JavaScript のコードから XPath の機能を使うための Mozilla のインターフェイスについて説明します。これらは DOM Level 3 XPath (現時点では W3C Working Group Note) に記載されているものです。
この記事は XPath それ自体について教えるものではありません。XPath についてよく知らなければ、 W3Schools XPath tutorial を参照して下さい。
ラッパ関数
次の関数を使うと、特定の XML ノードに対して XPath 式を評価する事ができます。第一引数は DOM ノードもしくは Document オブジェクトで、第二引数は XPath 式を定義した文字列です。
// 特定の DOM ノードもしくは Document オブジェクト (aNode) に対して // XPath 式 aExpression を評価し、その結果を配列として返す。 // 最初の作業を行った wanderingstan at morethanwarm dot mail dot com に感謝します。 function evaluateXPath(aNode, aExpr) { var xpe = new XPathEvaluator(); var nsResolver = xpe.createNSResolver(aNode.ownerDocument == null ? aNode.documentElement : aNode.ownerDocument.documentElement); var result = xpe.evaluate(aExpr, aNode, nsResolver, 0, null); var found = []; var res; while (res = result.iterateNext()) found.push(res); return found; }
この関数では new XPathEvaluator()
を使用しています。このコンストラクタは Mozilla 固有のものです。他のブラウザで使用される可能性のある Web ページのスクリプトでは、 new XPathEvaluator()
の呼び出しを次のコードに置き換えて下さい。
// XPathEvaluator は Document を実装するオブジェクトに実装されている var xpe = aNode.ownerDocument || aNode;
この場合、 XPathNSResolver の作成は次のように単純にできます。
var nsResolver = xpe.createNSResolver(xpe.documentElement);
ただ、 createNSResolver
は、 XPath 式の中の名前空間接頭辞が検索対象の文書のものと一致する場合にしか使うべきではないということに注意してください。一致しない場合には、独自の XPathNSResolver の実装を用意しなければなりません。
XMLHttpRequest を使って (Parsing and serializing XML にあるように) ローカルもしくはリモートの XML ファイルを DOM ツリーに読み込んだ場合には、 evaluateXPath()
の第一引数に req.responseXML
を指定します。
使用例
次のような XML 文書があるとします。 (How to create a DOM tree と Parsing and serializing XML も参照して下さい)
<?xml version="1.0"?> <people> <person first-name="eric" middle-initial="H" last-name="jung"> <address street="321 south st" city="denver" state="co" country="usa"/> <address street="123 main st" city="arlington" state="ma" country="usa"/> </person> <person first-name="jed" last-name="brown"> <address street="321 north st" city="atlanta" state="ga" country="usa"/> <address street="123 west st" city="seattle" state="wa" country="usa"/> <address street="321 south avenue" city="denver" state="co" country="usa"/> </person> </people>
関数 evaluateXPath
を使って、XPath 式でこの文書を「クエリ」する事ができます。DOM ツリーを走査しても同様の結果を得られますが、XPath 式を使った方がずっと高速で強力です。id
属性に頼る事ができれば document.getElementById()
は強力ですが、XPath の強力さには全く及びません。いくつか例を示します。
// 文書内の全ての人物の苗字を表示する var results = evaluateXPath(people, "//person/@last-name"); for (var i in results) alert("Person #" + i + " has the last name " + results[i].value); // 2 人目の人物のノードを得る results = evaluateXPath(people, "/people/person[2]"); // デンバーに住所を持つ全ての人物ノードを得る results = evaluateXPath(people, "//person[address/@city='denver']"); // 通りの名前に "south" が含まれる全ての住所を得る results = evaluateXPath(people, "//address[contains(@street, 'south')]"); alert(results.length);
資料
- XPath
- XPath Visualizer for Mozilla and Firefox
- XPath tutorial
- この話題に関するフォーラムでの議論
- Using the Mozilla JavaScript Interface to XPath - JavaScript から XPath を使用するためのチュートリアルの草稿