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に関する情報は、以下の記事でも詳しく解説しています。
ぜひ参考にしてみてください。
【関連記事】