1

この質問の変形はここで何度か尋ねられましたが、私の質問は、JavaでXPATHを使用する一般的な効率についての質問です。

私の仕事:地理的な場所に関するウィキペディアの記事を取り上げ、それらから階層的なデータ構造を作成します。

私はすでにwikiページのXMLバージョンを入手し、直感的に理解できるスキーマに従って再フォーマットしました。また、次のように、管理階層のさまざまなレベルを表す一連の非常に単純なクラスを作成しました。

public class Province implements java.io.Serializable {

private ArrayList<City> cities = new ArrayList<City>();
private String hanzi;
private String pinyin;


public Province(String hanzi, String pinyin) {
this.hanzi = hanzi;
this.pinyin = pinyin;
}

都市を追加するメソッド、いくつかのgetterメソッドとsetterメソッド、およびtoString()。

これが私が扱っているXMLファイルのタイプの例です:

<mediawiki>
     <page>
           <title>Tianjin</title>
           <revision>
                    <id>2064019</id>
                    <text xml:space="preserve">
                              <province>
                                       <hanzi>天津</hanzi>
                                       <pinyin>Tianjin</pinyin>

                                       <Level2>
                                               <hanzi>和平</hanzi>
                                               <pinyin>Heping</pinyin>
                                               <zip>300000</zip>
                                       </Level2>

                                       <Level2>
                                                <hanzi>河东</hanzi>
                                                <pinyin>Hedong</pinyin>
                                                <zip>300000</zip>
                                        </Level2>

                                </province>
                    </text>
            </revision>
      </page>

...

</mediawiki>

私は基本的にこの時点で機能的な設定をしていますが、コードは非常に反復的であり、地理データの固有の階層的性質を考慮していません。理想的には、特定のレベルで停止し(たとえば、特定の州に「焦点を合わせる」)、ドキュメント全体をクロールする回数を最小限に抑えるために、その時点からの相対的な用語でのみ参照することができます。例として(注:従来のドキュメント設定を抽象化して使用していますが、以下の方法は従来の方法にほぼ正確に対応しています)。

XPathReader reader = new XPathReader("sourceXML\\Provinces.xml");           
String expression = "/mediawiki/page";
NodeList allProvinces = (NodeList)reader.read(expression, XPathConstants.NODESET);

for(int i=0; i < allProvinces.getLength(); i++) {
     expression = "/mediawiki/page[" + i + "]/revision/text/province/hanzi";
     String hanzi = reader.read(expression, XPathConstants.STRING).toString();

     expression = "/mediawiki/page[" + i + "]/revision/text/province/pinyin";
     String pinyin = reader.read(expression, XPathConstants.STRING).toString();

     Province currProv = new Province(hanzi, pinyin);         



     expression = "/mediawiki/page[" + i + "]/revision/text/province/Level2";
     NodeList level2 = (NodeList)reader.read(expression, XPathConstants.NODESET);

     for(int j=1; j < level2.getLength(); j++) {
           expression = "/mediawiki/page[" + i + "]/revision/text/province/Level2[" + j + "]/hanzi";
           String hanzi2 = reader.read(expression, XPathConstants.STRING).toString();   

           expression = "/mediawiki/page[" + i + "]/revision/text/province/Level2[" + j + "]/pinyin";
           String pinyin2 = reader.read(expression, XPathConstants.STRING).toString();  

         City currCity = new City(hanzi2, pinyin2);
         currProv.add(currCity);
...
     }
}   

率直に言って、これはばかげているようです。私が関心のあるレベルに到達すると、これらの文字列に関するすべてが同一であるという事実を考慮していません。私はいかなる種類の相対パスも参照していません。ドキュメントの一部をトラバースするときは常に、実際には全体をトラバースします。元のXMLドキュメントの残りの部分をしばらくブロックして、それ以降のすべてを相対的な用語で参照し、自分の州だけに焦点を当てることができれば素晴らしいと思います。

特に、これが「読み取り」抽象化の背後にあるコストがどれほど高いかに注意する必要があります。

xPath.compile(expression);
String result = xPathExpression.evaluate (xmlDocument, returnType);

私は本質的に、わずかに異なるエンディングで同じパターンを再コンパイルしていますか?関心のある部分をロードしてから、その子を「currProv / hanzi」のようなもので参照するのはどうですか?

XMLを解析する他の方法を調べましたが、「Digester」は私が望むものと似たようなことをしているようですhttp://commons.apache.org/digester/core.htmlですが、このXPATHにはすでにほとんどすべてのものがあります。実装。

この問題の解決策は非常に単純であると私はしつこく疑っています...しかし、私は解決策を完全に把握することはできません。とにかく、お時間をいただきありがとうございました!

4

1 に答える 1

1

相対的なネストされたXPathがその方法です。

私はEclipseLinkJAXB実装(MOXy)を主導しており、@XmlPathアノテーションを介してこの機能を提供しています。すでにXPathがある場合は、比較的簡単にマッピングできます。

詳細については、以下を参照してください。

于 2010-12-16T11:01:11.177 に答える