プログラミング言語とXPath(2)

最初はJavaです.JavaXPathを使用する例はネット上で豊富に存在します.私が懐かしく見させていただいたのは、IBM developerWorks Japanの以下の記事です.

Java プログラムから XML をクエリーする

何故なつかしいのかというと、この記事を書いたElliotte Rusty Haroldさんは、Processing XML with Javaという本の著者で、昔私がJavaXSLTのソリューションを作るとき、それは大変お世話になったからです.そのソリューションはJavaのSwingでGUIを作って、そこでXSLTをJAXP(Java API for XML Processing)で動かし、更にXSLTスタイルシートからはJavaのファンクション(staticなメソッド)を呼ぶと言うものでしたが、当時このようなことをやろうとしても和書にはまったくリソースがありませんでした.ようやくこの本をAmazonで探し当て、必死に読んでプログラムを作ったものでした.2002年に出た本なので、もう時代と共にこの本も古くなってしまいしたが、今でもamazon.comで見ると五つ星評価です.

本は会社に置いてきてしまったので、Amazonから画像をお借りしました.

イメージ 1

Processing XML with Java


さて、JavaではXPathを使う典型的な例は、DOMツリーにXMLファイルを展開してから、XPath式をコンパイルして、コンテキスト(DOMツリーの中の位置)と、結果の型を指定してXPathExpressionクラスのevaluateメソッドを呼び出します.先だって紹介したMusicLibrary.xmlhttp://blogs.yahoo.co.jp/tnakita/14649736.html)から、1994年のアルバム名を表示する例を以下に示します.

import java.io.IOException;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import javax.xml.parsers.*;
import javax.xml.xpath.*;

public class XPathExample {

    public static void main(String[] args) 
            throws ParserConfigurationException, SAXException,
            IOException, XPathExpressionException{
        
            DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
            domFactory.setNamespaceAware(true);
            DocumentBuilder builder = domFactory.newDocumentBuilder();
            Document doc = builder.parse("MusicLibrary.xml");
            
            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();
            XPathExpression expr 
             = xpath.compile("/musicLibrary/cd[string(year) = '1994']/title/text()");
            Object result = expr.evaluate(doc, XPathConstants.NODESET);
            NodeList nodes = (NodeList) result;
            for (int i = 0; i < nodes.getLength(); i++) {
                System.out.println(nodes.item(i).getNodeValue()); 
            }
    }
}

このプログラムを実行すると、

The Dark Side of the Moon

と表示されます.

では、次のようにするとどうなるでしょう?

XPathExpression expr 
 = xpath.compile("/musicLibrary/cd[matches(string(artist),'^P.+ F.+')]/title/text()");

これはartistの最初の文字が"P"で、あとに文字が続いて、空白が1文字あって"F"と続く、つまりPink Floydにマッチさせる条件です.実行すると、

Exception in thread "main" javax.xml.transform.TransformerException: 関数: matches が見つかりませんでした
 at com.sun.org.apache.xpath.internal.compiler.XPathParser.error(Unknown Source)

のエラーになります.何故かというとmatches()という関数はXPath1.0にはなくて、標準のJavaXPathの実装では処理できないからです.でも、

XPathFactory factory = XPathFactory.newInstance();

の前に、

System.setProperty("javax.xml.xpath.XPathFactory","net.sf.saxon.xpath.XPathFactoryImpl");

と一行入れてやって、XSLTプロセッサのSaxon9のsaxon9xx.jar(xxはプロダクトにより異なる)をCLASSPATHに加えてやると、ちゃんと

The Dark Side of the Moon

と表示されます.つまりXPath2.0が使えるようになります.こういう自由度の高いところがJava(というかJAXP)のいいところに思えます.利用者が自由にXSLTのインプリメンテーションを選べるのです..NETはあまりこういう思想がないように思えます.

さてJavaではちゃんとXPathが使えることがわかりました.このプログラムでもXSLTスタイルシートに比べれば結構複雑だと感じるかもしれません.しかしこれをDOM APIでシコシコやった日には日が暮れてしまうでしょう.という訳でXPath1.0も2.0も使えるのはJavaのいいところだと思います.次は、Visual BasicかF#で.NETの世界を見てみたいと思います.