Java:如何将XML流拆分为小型XML文档?流式XML解析器上的XPath?

时间:2009-10-28 22:16:23

标签: java xml streaming

我需要从网络中读取大型XML文档并将其拆分为较小的XML文档。特别是我从网络上读取的流看起来像这样:

<a> <b> ... </b> <b> ... </b> <b> ... </b> <b> ... </b> .... </a>

我需要将其分解为

<a> <b> ... </b> <a>

(我实际上只需要<b> .... </b>部分,只要声明更高的命名空间绑定(例如在<a>中)移动到<b>,如果这样可以更容易)。

该文件对于DOM样式解析器来说太大了,必须完成流式传输。是否有任何XML库可以做到这一点?

[编辑]

我认为我理想的是能够在XML流上执行XPath查询,其中流解析器只在必要时解析以返回结果节点集中的下一个项(及其所有属性)和孩子们)。不一定是XPath,而是一些想法。

谢谢!

5 个答案:

答案 0 :(得分:2)

带SAX过滤器的JAXP SAX api既快速又高效。可以看到好的介绍过滤器here

答案 1 :(得分:1)

作为XML拆分器,VTD-XML非常适合此任务......它的内存效率也比DOM高。简化编码的关键方法是VTDNav的getElementFragment()...下面是将split input.xml拆分为out0.xml和out1.xml的Java代码

<a> <b> text1 </b>  <b> text2 </b> </a>

进入

<a> <b> text1</b> </a> 

<a> <b> text2</b> </a>

使用XPath

/a/b

代码

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

public class split {
    public static void main(String[] argv) throws Exception{
        VTDGen vg = new VTDGen();
        if (vg.parseFile("c:/split/input.xml", true)){
            VTDNav vn = vg.getNav();
            AutoPilot ap = new AutoPilot(vn);
            ap.selectXPath("/a/b");
            int i=-1,k=0;
            byte[] ba = vn.getXML().getBytes();
            while((i=ap.evalXPath())!=-1){
                FileOutputStream fos = new FileOutputStream("c:/split/out"+k+".xml");
                fos.write("<a>".getBytes());
                long l = vn.getElementFragment();
                fos.write(ba, (int)l, (int)(l>>32));
                fos.write("</a>".getBytes());
                k++;
            }
        }       
    }
}

如需进一步阅读,请访问http://www.devx.com/xml/Article/36379

答案 2 :(得分:1)

去上学

StringBuilder buffer = new StringBuilder(1024 * 50);
BufferedReader reader = new BufferedReader(new FileReader(pstmtout));
String line;
while ((line = reader.readLine()) != null) {
  buffer.append(line);
  if (line.equalsIgnoreCase(endStatementTag)) {
    service.handle(buffer.toString());
    buffer.delete(0, buffer.length());
  }
}

答案 3 :(得分:1)

您可以使用XProc语言

执行此操作
<?xml version="1.0" encoding="ISO-8859-1"?>
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" version="1.0">
  <p:load href="in/huge-document.xml"/>
  <p:for-each>
    <p:iteration-source select="/a/b"/>
    <p:wrap match="/b" wrapper="a"/>
    <p:store>
       <p:with-option name="href" select="concat('part', p:iteration-position(), '.xml')">
          <p:empty/>
       </p:with-option>
    </p:store>
  </p:for-each>
</p:declare-step>

你可以使用QuiXProc(Streaming XProc实现:http://code.google.com/p/quixproc/)来尝试流式传输

答案 4 :(得分:0)

我碰巧喜欢XOM XML库,因为它的界面简单,直观且功能强大。要使用XML执行所需操作,您可以使用自己的NodeFactory和(例如)覆盖finishMakingElement()方法。如果它正在制作你想要的元素(在你的情况下,<b>),那么你将它传递给你需要做的任何事情。