Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 高效地将多个大型xml文件合并为一个_Java_Xml_Xslt_Sax_Stx - Fatal编程技术网

Java 高效地将多个大型xml文件合并为一个

Java 高效地将多个大型xml文件合并为一个,java,xml,xslt,sax,stx,Java,Xml,Xslt,Sax,Stx,我在网上搜索,上下搜索。没有解决办法。尽管我找到了在纯xslt中实现这一点的解决方案 但问题是,生成的xml将有几百MB大。所以我必须用Java中的SAX来实现这一点。(请不要使用xslt解决方案,尽管我用xslt标记了它;-)) 让我详细解释一下。我有几个应该解析的多个xml文件(最好是InputSteam)。文件或InputStream的 输入流1 <root> <doc> <tag>test1</tag> </doc&g

我在网上搜索,上下搜索。没有解决办法。尽管我找到了在纯xslt中实现这一点的解决方案

但问题是,生成的xml将有几百MB大。所以我必须用Java中的SAX来实现这一点。(请不要使用xslt解决方案,尽管我用xslt标记了它;-))

让我详细解释一下。我有几个应该解析的多个xml文件(最好是InputSteam)。文件或InputStream的

输入流1

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

或者我应该直接在ContentHandler中解析InputStreams吗?

您可能想看看Saxon的付费版本。它可以动态处理XSLT,而不需要在内存中使用完整的DOM。

我自己也没有这样做过,但我记得看过一篇IBM developerworks文章,这篇文章似乎让这变得非常简单

现在有点旧了,试试看


这是StAX而不是SAX。我不确定当前的jdk是否包含StAX。如果没有,您可能可以从

中获得它。我最终通过以下代码片段实现了这一点:

  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。如果读取所有inputstreams,customHandler.createNextInputStream方法将返回null。

合并文件的最有效方法是使用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");   
    }
}

嗯,在xslt中,无论您在哪里,都可以查找第一个节点和最后一个节点。Ie:一切都需要在记忆中。。。根据xslt的定义。或者你怎么想?有相当大的XSLT程序子集,你不需要在内存中使用完整的DOM树来执行。hmmh,但我不想在内存中使用它们。。。只需将它们直接导入光盘即可。我不明白这怎么会比sax快。感谢vtd xml提示。它看起来很有希望(从我在sourceforge网站上看到的内容来看)。但尽管它可能快100倍。如果它需要文档的100%RAM(甚至更多),我就不能使用它:可能是生成的xml甚至无法放入内存。请注意,张先生是VTD-xml的作者。+1 JDK包括StAX,因为据我所知是1.5。使用起来比SAX方便得多。
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
xmlReader.setContentHandler(customHandler);
xmlReader.parse(getInputSource()); // only one InputStream possible
  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();
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");   
    }
}