2010-12-16 58 views
1

這個問題的變體現在已經有幾次被問到了,但我的問題更多的是在Java中使用XPATH的一般效率問題。使用Java中的XPATH處理分層XML文檔。效率?

我的任務:獲取維基百科關於地理位置的文章,並從中創建分層數據結構。

我已經獲得了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實現中擁有幾乎所有的東西。

我對這個問題的解決方案非常簡單,我有嘮叨的懷疑......但我無法完全理解解決方案。無論如何,我感謝你的時間!

回答