Java で XPath を使う方法

注意 [2009.10.13]

この記事で書かれている方法は、W3C DOM 3 XPath Specification とは異なる独自実装を用いています。
W3C DOM 3 XPath の勧告に従った方法で XPath を評価する という記事を書きましたので、そちらに記した方法で XPath 式を実行することをおすすめします。

本文

JavaXPath を使う方法に関しては javax.xml.xpath.XPath vs org.apache.xpath.XPathAPI という文書を読むとよくわかる。 が、各クラスの名前空間が明示されていなくてちょっと悩むかも。 というわけで import 文で名前空間を明示したサンプルコードを書いた。

XML名前空間に関する部分は含んでいない。 なお、読み込んだ XML ファイルは さきほど書いた記事ソースコード中にあるものと同等である。

package info.vividcode;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.traversal.NodeIterator;

import com.sun.org.apache.xpath.internal.XPathAPI;

public class Test {
    
    public static void main( String[] args ) {
        try {
            // ===== XML 文書の読み込み =====
            DocumentBuilder builder = DocumentBuilderFactory.newInstance()
                                                        .newDocumentBuilder();
            Document doc = builder.parse( new File("file.xml") );
            // ===== javax.xml.xpath.XPath を使う方法 =====
            // 準備
            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();
            // 単一ノード取得
            String location = "/test/t1/text/text()";
            System.out.println( xpath.evaluate(location, doc) );
            // 複数ノード取得
            location = "//t1/t2[2]/text()";
            NodeList entries = (NodeList) xpath.evaluate(
                                    location, doc, XPathConstants.NODESET );
            for( int i = 0; i < entries.getLength(); i++ ) {
                System.out.println( entries.item(i).getNodeValue() );
            }
            // ===== org.apache.xpath.XPathAPI を使う方法 =====
            // 単一ノード取得
            location = "/test/t1/text/text()";
            System.out.println( XPathAPI.eval(doc, location) );
            // 複数ノード取得
            //location = "//t1/t2[2]/text()";
            location = "/descendant::t2[2]/text()";
            NodeIterator it = XPathAPI.selectNodeIterator(doc, location);
            Node node;
            while( (node = it.nextNode()) != null ) {
                System.out.println( node.getNodeValue() );
            }
        } catch ( Exception e ) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
}

m2eclipse を使用してプロジェクトのビルドを行う際に FileNotFoundException が発生する問題

私は、Java アプリケーションの開発を行う際に統合開発環境 (IDE) として Eclipse を使用しており、プロジェクト管理ツールとして Apache Maven 2 を使用しています。 また、Eclipse から Maven 2 を使うために m2eclipse (Eclipseプラグイン) を使用しています。

んで今日は別の PC に新たに Java の開発環境を構築したのですが、プロジェクトのビルドをしようとすると FileNotFoundException が発生してビルドができないという問題に直面しました。 表示されたメッセージは以下。

java.io.FileNotFoundException: C:\Documents and Settings\nobuoka\繝?せ繧ッ繝医ャ繝予eclipse galileo\configuration\org.eclipse.osgi\bundles\312\1\.cp\org.maven.ide.eclipse.cliresolver.jar
at org.codehaus.plexus.classworlds.launcher.Configurator.configure(Configurator.java:333)
at org.codehaus.plexus.classworlds.launcher.Launcher.configure(Launcher.java:131)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:404)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:351)
at org.codehaus.classworlds.Launcher.main(Launcher.java:31)

10 時間ぐらい色々悩んでいたんですが、結局、Eclipse のパスに非 ascii 文字が含まれているとダメだということがわかりました。 m2eclipse なんて使ってる人あんまり居なさそうだけど、m2eclipse を使う場合は Eclipse の置き場所にご注意ください。

例外が発生した PC の環境は以下です。

Eclipse を起動しようとすると 「JRE が見つからない」 と怒られてしまう問題


問題

JDK のバージョンを新しくして、Eclipse を起動しようとすると

A Java Runtime Environment (JRE) or Java Development Kit (JDK) must be available in order to run Eclipse. No Java virtual machine was found after searching the following locations:

C:\Program Files\Java\jdk1.6.0_07\jre\bin\javaw.exe
と怒られてしまった。 要約すると 「JRE or JDK が見つからない」 ということ。

"C:\Program Files\Java\jdk1.6.0_07\jre\bin\javaw.exe" というのがアップデート前のパス。 アップデート後は "C:\Program Files\Java\jdk1.6.0_14\jre\bin\javaw.exe" なので、当然古いパスでは見つかるはずもない。 問題はなんで古いほうのパスを見に行くのかということで、システムの環境変数をチェックしてみるも問題なし。 ネットで調べてみるも、「Eclipse が (同様のエラーメッセージで) 起動しない」 という問題に対して 「環境変数JDK or JRE へのパスを追加する」 という対処法しかなくてちょっと困ってしまった、というお話。

ちなみに OS は Windows XP SP3 HomeEdition。

解決策

対処法はすっごく単純。 実は Eclipse のインストールディレクトリに "eclipse.ini" というファイルがあって、ここに JDK or JRE のパスが書いてあるので、これを書き直せばよい。