繁体   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