簡體   English   中英

高效地將多個大型xml文件合並為一個

[英]Efficient merging of multiple, large xml files into one

我搜索了網絡,我上下搜索stackoverflow。 沒有解決方案。 雖然我在這里找到了解決方法如何在純xslt中執行此操作

但問題是產生的xml將是幾百MB大。 所以我必須用Java中的SAX來做這件事。 (請不要xslt解決方案,雖然我用xslt標記它;-))

讓我更詳細地解釋一下。 我有幾個應該解析的多個xml文件(最好是InputSteam)。 文件或InputStream看起來像

inputstream1

<root>
  <doc>
    <tag>test1</tag>
  </doc>
  <doc>
    <tag>test2</tag>
  </doc>
  ...
</root>

inputstream2

<root>
  <doc>
    <tag>test3</tag>
  </doc>
  <doc>
    <tag>test4</tag>
  </doc>
  ...
</root>

inputstream1 + inputstream2 + ... + inputstreamN = 結果xml 它看起來像

<root>
  <doc>
    <tag>test1</tag>
  </doc>
  <doc>
    <tag>test2</tag>
  </doc>
  ...
   <doc>
    <tag>test3</tag>
  </doc>
  <doc>
    <tag>test4</tag>
  </doc>
  ...
</root>

有人有解決方案或鏈接嗎? 這是通過實現自定義InputSource還是應該使用自定義ContentHandler? 或者這可能與joost / stx一起使用嗎?

如果我可以使用ContentHandler那么好的事情就是我可以應用一些小的轉換(我已經實現了這個)。 但問題是我不知道將多個文件或InputStream作為InputSource傳遞的方法:

XMLReader xmlReader = XMLReaderFactory.createXMLReader();
xmlReader.setContentHandler(customHandler);
xmlReader.parse(getInputSource()); // only one InputStream possible

或者我應該直接在ContentHandler中解析InputStreams?

我自己沒有這樣做,但我記得看到一篇IBM developerworks文章看起來很容易。

它現在有點舊了,但請嘗試http://www.ibm.com/developerworks/xml/library/x-tipstx5/index.html

這是StAX而不是SAX。 我不確定當前的JDK是否包含StAX。 如果沒有,你可以從http://stax.codehaus.org/獲得它

您可能想看看Saxon的付費版本。 它可以處理即時XSLT,而不需要內存中的完整DOM。

我終於通過以下片段進行了管理:

  finalHandler = new StreamResult(new OutputStreamWriter(System.out));
  // customHandler extends DefaultHandler
  CustomTransformerHandler customHandler = new CustomTransformerHandler(
         finalHandler);
  customHandler.startDocumentExplicitly();
  InputStream is = null;
  while ((is = customHandler.createNextInputStream()) != null) {
    // multiple inputStream parsing
    XMLReader myReader = XMLReaderFactory.createXMLReader();
    myReader.setContentHandler(customHandler);
    myReader.parse(new InputSource(is));
  }
  customHandler.endDocumentExplicitly();

重要的是將startDocument和endDocument方法留空。 所有其他方法(字符,startElement,endElement)將被重定向到finalHandler。 如果讀取所有輸入流,則customHandler.createNextInputStream方法返回null。

合並文件的最有效方法是使用VTD-XML ,AFAIK提供的字節級剪切和粘貼功能。 你獲取兩個文件,將它們解析為VTDNav對象,然后實例化一個XMLModifier對象,從第二個文件中獲取片段,然后將它們插入到第一個文件中......這比SAX更有效..同時得到的XML將書寫方向寫入文件 - 無需將其存儲在內存中。 以下是不到20行的完整代碼......

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

public class merge {
    // merge second.xml into first.xml assuming the same encoding
    public static void main(String[] s) throws VTDException, IOException{
        VTDGen vg = new VTDGen();
        if (!vg.parseFile("d:\\xml\\first.xml", false))
            return;
        VTDNav vn1=vg.getNav();
        if(!vg.parseFile("d:\\xml\\second.xml", false))
            return;
        VTDNav vn2 = vg.getNav();
        XMLModifier xm = new XMLModifier(vn1);
        long l = vn2.getContentFragment();
        xm.insertBeforeTail(vn2, l);
        xm.output("d:\\xml\\merged.xml");   
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM