2012-09-10 51 views
2

我是Java中的新手,在評估了一些java庫之後,我通過它的性能測試和選擇使用Xpath選擇了VTD-XML,我試過了StaX,我認爲它不適合人類,真的很難理解解析是如何工作的(幾乎對我來說XD)。如何通過VTD-XML中的節點名稱值來合併(連接)兩個不同的xml文件?

所以,我的目標是 「注入」 從partial_geo_codes.xml的GEO_CODE節點到GEO_CODE accommodations.xml來自

accommodation.xml

<accommodations> 
<accommodation> 
    <ext_id>12345</ext_id> 
    <type>A</type> 
    <details>D</details> 
    <geo_code /> 
    </accommodation> 

節點EXT_ID值匹配

,這是要添加到accommodation.xml中的文件:

partial_geo_codes.xml

<geo_codes> 
<geo_code> 
    <ext_id>12345</ext_id> 
    <geo_idlocacion>77500</geo_idlocacion> 
    <latitude>42.578114</latitude> 
    <longitude>1.648293</longitude> 
    </geo_code> 
    <geo_code> 
     ... 
    <geo_code> 
    <geo_code> 
     ... 
    <geo_code> 
<geo_codes> 

這是預期的輸出:

accommodation_new.xml

<accommodations> 
<accommodation> 
    <ext_id>12345</ext_id> 
    <type>A</type> 
    <details>D</details> 
    <geo_code> 
    <ext_id>12345</ext_id> 
    <geo_idlocacion>77500</geo_idlocacion> 
    <latitude>42.578114</latitude> 
    <longitude>1.648293</longitude> 
    <geo_code> 
    </accommodation> 
    <accommodation> 
    ..... 
    </accommodation> 
    ...... 
</accommodations> 

,這是我的 「崇拜者 - 真的,很爛」 的Java類:

import com.ximpleware.extended.*; 
import java.io.*; 

public class MergeVtd { 

public static void main(String args[]) throws Exception { 

    String filesPath = new java.io.File("").getAbsolutePath() .concat("/main/src/"); 
    long start = System.currentTimeMillis(); 


    //init original xml 
    VTDGenHuge vgh = new VTDGenHuge(); 
    //init tobemerged xml 
    VTDGenHuge vgm = new VTDGenHuge(); 


    if (vgm.parseFile(filesPath.concat("partial_geo_code.xml"),true,VTDGenHuge.MEM_MAPPED)){ 

     VTDNavHuge vnm = vgm.getNav(); 
     AutoPilotHuge apm = new AutoPilotHuge(vnm); 
     apm.selectElement("ext_id"); 


     int count=0; 
     while (apm.iterate()){ 
      int t = vnm.getText(); 
      if (t!=-1) { 
       System.out.println("Value vnm ==> "+vnm.toNormalizedString(t)); 

      //we have id to match.... 

      if (vgh.parseFile(filesPath.concat("accommodation.xml"),true,VTDGenHuge.MEM_MAPPED)){ 
       VTDNavHuge vnh = vgh.getNav(); 
       AutoPilotHuge aph = new AutoPilotHuge(vnh); 
       aph.selectXPath("/accommodations/accommodation/ext_id[text()='" + vnm.toNormalizedString(t) + "']"); 


       int result = -1; 
       while ((result=aph.evalXPath())!=-1){ 
        int g = vnh.getText(); 
        if (g!=-1) { 
         System.out.println("Value vnh ==> "+vnh.toNormalizedString(g)); 

        } else { 
         System.out.println("no match in vnh !======= "); 
        } 
       } 
      } 

      } 

      System.out.println("============================== " + count); 
      count++; 

     } 

    } 

    long end = System.currentTimeMillis(); 
    System.out.println("Execution time was "+ (end - start) +" ms."); 
    System.exit(0); 

} 

} 

我真的很感激任何線索都會幫助我如何一次迭代到2個xml文件並通過ext_id節點值合併得更快,現在真的需要太多時間。

+0

你是否期待ext_ids在這兩個文件中排序? – jtahlborn

+0

@jtahlborn我想從partial_geo_codes.xml中「注入」節點到 accomusion.xml中,這兩個節點都匹配來自 – jipipayo

+0

的節點上的值yes,我意識到你正在嘗試做什麼。你目前的代碼似乎只是從兩個文件中選擇ID?你是試圖合併「即時」還是建立一套地圖併合併成另一套? – jtahlborn

回答

1

partial_geo_codes.xml有多大?它能適應內存嗎?如果是,那麼我會建議使用哈希映射對其進行索引。只需創建簡單的HashMap,並將那些以ext_id的值作爲關鍵字的geo_code節點的引用。

完成該操作後,您只需要傳遞一次accomodations.xml。現在你的算法複雜度是O(n^2),更糟糕的是,它涉及從磁盤讀取n個數據!使用HashMap的版本將花費O(n)時間,並且只需要通過兩個xml文件單次傳遞。

+1

謝謝伊萬,是的,我要製作一個hashmap。部分xml的大小是3M,但不會是一個固定的大小,這個類將處理從2M到100M的文件。另一種選擇呢?要使用litle數據庫引擎創建一個索引表?像h2? http://www.h2database.com/html/main.html – jipipayo

+1

我認爲這取決於geo_code的結構是否更改。因爲您可以在填充accomodations.xml時創建一個包含3列的表格:geo_idlocacion,緯度,經度,並創建goe_code節點及其子節點。作爲一個附註,我用[hsqldb](http://hsqldb.org/)取得了很好的結果,我將它作爲另一個選項,我從未使用過h2。最後,我會說如果你可以將它放在內存中,那麼哈希映射就足夠了。 –

相關問題