JavaのXPathとは?

XPathとは、XML文書の特定の部分をパスで指定する方法です。
パスを利用して、必要な情報がどこにあるのかを表すため、 パスを入力とした抽出処理を考えられるようになります。
XPath自身はXML文書というわけではなく、XML文書の一部分として働きます。
XPathのデータモデルの場合、XMLデータを下記の7種類のノードで構成したツリーと考えます。
- ルートノード:最上位ノード
- 要素ノード:XML の要素を表すノード
- テキストノード:開始タグと終了タグで挟まれた文字列データ
- 属性ノード:要素内で指定された属性を表すノード
- 名前空間ノード:名前空間 (Namespace) を表すノード ※1
- 処理命令ノード:処理命令 (Processing Instruction) を表すノード
- コメントノード:コメントを表すノード ※ただし、ドキュメント型宣言内に記述するコメントを除きます。
※1 処理命令とは、「 <?」 と 「?>」 で挟まれた一文を指します。XML宣言は処理命令の形をしていますが、XML 1.0 の構文上、処理命令ではないことからXML宣言は処理命令ノードとしては扱いません。
基本的には、UNIX系の階層型ファイル・システムのパスと同様に指定可能です。
加えて、関数や式を組み合わせて複雑な指定もできるようになっています。
evaluateメソッドとは?
evaluateメソッドは、コンテキストでXPath式を評価して、結果をStringとして返すXPathのメソッドです。
使い方には4種類あり、それぞれ下記の通りとなっています。
| 修飾子と型 | メソッドと説明 |
|---|---|
| String | evaluate(String expression, InputSource source) 指定されたInputSourceのコンテキストでXPath式を評価し、結果をStringとして返します。 |
| Object | evaluate(String expression, InputSource source, QName returnType) 指定されたInputSourceのコンテキストでXPath式を評価し、結果を指定された型として返します。 |
| String | evaluate(String expression, Object item) 指定されたコンテキストでXPath式を評価し、結果をStringとして返します。 |
| Object | evaluate(String expression, Object item, QName returnType) 指定されたコンテキストでXPath式を評価し、結果を指定された型として返します。 |
また、XPath式の評価は下記の通りです。
| XPath式の評価 | |
|---|---|
| コンテキスト | コンテキスト項目がない式を評価する要求が行われた場合、コンテキストには空の ドキュメント・ノードが使用される。XPath式を評価するため、DocumentFragmentが ドキュメント・ノードと同様に扱われる。 |
| 変数 | 式に変数の参照が含まれる場合、setXPathVariableResolver(XPathVariable Resolver resolver)で設定されたXPathVariableResolverによってその値が見つけられる。 変数リゾルバが定義されていないか、リゾルバから変数に対してnullが返された場合、XPathExpressionExceptionが生成される。 変数の値は、1回の評価の過程を通じて不変でなければならない。 |
| 関数 | 式に関数の参照が含まれる場合、setXPathFunctionResolver(XPathFunction Resolver resolver)で設定されたXPathFunctionResolverによって関数が見つけられる。 関数リゾルバが定義されていないか、関数リゾルバから関数に対してnullが返された場合、 XPathExpressionExceptionが生成される。 |
| QName | 式の中のQNameはsetNamespaceContext(Name spaceContext nsContext)で 設定されたXPath名前空間コンテキストと照らして解決される。 |
| 結果 | 式の評価の結果は目的の戻り値の型のインスタンスに変換される。 有効な戻り値の型は、XPathConstantsに定義する。戻り値の型への変換はXPath変換規則に従う。 |
参照:XPath (Java Platform SE 8 )
XPathの使い方(ロケーションパス)

XPathでXML文書のノードを指定するものを「ロケーションパス」と言います。
ロケーションパスは、スラッシュで区切ることでノード階層を表すものです。
ロケーションパスは、ルートノードから指定する”絶対ロケーションパス”と、任意のノードを起点とする”相対ロケーションパス”の2つがあります。
そして、起点とするノードのことをコンテキスト(文脈)ノードと言い、絶対ロケーションパスは、コンテキストノードがルートノードであるロケーション・パスです。
例えば、次のXML文書を参考にロケーションパスを記述してみます。
<?xml version="1.0" encoding="UTF-8"?>
<member>
<user id="P210401" sex="male">
<name>田中 太郎</name>
<contact kind="email">tanaka@potepan.com</contact>
<contact kind="url">https://style.potepan.com/tanaka</contact>
<image file="tanaka01.png" />
</user>
<user id="P210401" sex="female">
<name>佐藤 花</name>
<contact kind="email">satou@potepan.com</contact>
<contact kind="url">https://style.potepan.com/satou</contact>
<image file="satou03.png" />
</user>
<user id="P210401" sex="male">
<name>鈴木 裕斗</name>
<contact kind="email">suzuki@potepan.com</contact>
<contact kind="url">https://style.potepan.com/suzuki</contact>
<image file="suzuki05.png" />
</user>
</member>
user要素配下のname要素を示すために、絶対ロケーションパスは次のように記述できます。
/member/user/name
上記の絶対ロケーションパスの結果でマッチするのは、3つのname要素ですね。
また、ルートとそのすべての子孫ノードのname要素にマッチさせるためには、下記のように記述もできます。
//name
XPathを取得する

JavaでXPathから要素を取得するサンプルです。
■記述例
public void GetXpath(String xmlPath,String xpathStr) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
try {
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new File(xmlPath));
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList nl = (NodeList)xpath.evaluate(xpathStr, doc, XPathConstants.NODESET);
int num = nl.getLength();
for(int i=0;i<num;i++) {
Node node1 = nl.item(i);
NodeList nl2 = node1.getChildNodes();
int num2 = nl2.getLength();
for(int j=0;j<num2;j++) {
Node node2 = nl2.item(j);
if(node2.getNodeType() == Node.TEXT_NODE) {
System.out.println(node2.getTextContent());
}
}
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XPathExpressionException e) {
e.printStackTrace();
}
}
また、その他XMLに関する情報は、以下の記事でも詳しく解説しています。
ぜひ参考にしてみてください。
【関連記事】