Java5 XPath
J2SE1.5.0_05で試しています。
以下のようなXML文書を:
<?xml version="1.0"?> <plugin xmlns="http://d.hatena.ne.jp/bellbind/plugin/1.0" id="foo.bar"> <extension-point id="foo.bar.Ext" class="foo.FooExt" version="1"/> <extension-point id="foo.bar.Ext2" class="foo.FooExt2" version="2"/> </plugin>
XPathを使って解析するJavaプログラムを書いてみます:
import java.io.*; import javax.xml.parsers.*; import javax.xml.xpath.*; import org.w3c.dom.*; import org.xml.sax.*; public class XPathReading { public static void main(String[] args) throws IOException, ParserConfigurationException, SAXException, XPathExpressionException { DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document document1 = builder.parse(new File("plugin.xml")); XPath xpath = XPathFactory.newInstance().newXPath(); String pluginId = xpath.evaluate("/plugin/@id", document1); // result type: String System.out.println(pluginId); // pre-compile XPathExpression extensionPointPath = xpath.compile("/plugin/extension-point"); // NodeList type NodeList extensionPoints = (NodeList) extensionPointPath.evaluate(document1, XPathConstants.NODESET); for (int i = 0; i < extensionPoints.getLength(); i++) { Element extensionPoint = (Element) extensionPoints.item(i); System.out.println(extensionPoint.getAttribute("id")); // dom api System.out.println(xpath.evaluate("@class", extensionPoint)); // xpath api Double version = (Double) xpath.evaluate("@version", extensionPoint, XPathConstants.NUMBER); System.out.println(version.intValue()); } } }
さすがJavaなので長い。結果:
$ java -classpath . XPathReading foo.bar foo.bar.Ext foo.FooExt 1 foo.bar.Ext2 foo.FooExt2 2
XPathエンジンの取得は、デフォルトのエンジンを使うのであれば以下のとおり。
XPath xpath = XPathFactory.newInstance().newXPath();
XPathFactoryファクトリーオブジェクトはエンジンプログラムのタイプごとに切り替えられます。XPathエンジンは、同じ名前空間エリアス、変数参照や関数定義(ユーザー定義のものが設定できる)を使う範囲で使いまわせます。
XPath評価はevaluateメソッドです。戻り値を指定しない場合は文字列、指定した場合はそれにあった型でかえります。型は自分で適切なものを選択しなくてはいけません。
- たとえばElementを返すXPathで戻り値を指定しないと、空文字列になります。
- 複数のノードを返すものはNodeListにしないかぎり、はじめの一つだけが返ります。
String value = xpath.evaluate(xpathExp, node);
String value = (String) xpath.evaluate(xpathExp, node, XPathConstants.STRING);
boolean value = (Boolean) xpath.evaluate(xpathExp, node, XPathConstants.BOOLEAN);
Double value = (Double) xpath.evaluate(xpathExp, node, XPathConstants.NUMBER);
Node value = (Node) xpath.evaluate(xpathExp, node, XPathConstants.NODE);
NodeList value = (NodeList) xpath.evaluate(xpathExp, node, XPathConstants.NODESET);
第二引数はDocumentやElementなどが渡せます。NodeListやFileなどは直接渡せませんでした。
XPathExpressionはプリコンパイル形式で、固定のXPath式を使いまわすときに処理速度があがるでしょう。メソッドはevaluateのみで、引数はXPathのevaluateの第一引数がなくなっただけです。