如何在一个文档中解析多个连续的xml文件?

问题描述:

我有一个很大的文本文件,XML的有效证件的序列看起来是这样的:如何在一个文档中解析多个连续的xml文件?

<DOC> 
    <TEXT> ... </TEXT> 
    ... 
</DOC> 
<DOC> 
    <TEXT> ... </TEXT> 
    ... 
</DOC> 

等没有<?xml version="1.0">,该<DOC></DOC>界定每个单独的XML。在Java中解析这个问题的最佳方式是什么?在<DOC>中获取<TEXT>下的值?

如果我将整个事情传递给一个DocumentBuilder,我会收到一个错误,指出文档格式不正确。有没有比简单遍历更好的解决方案,建立一个字符串为每个<DOC>

A 有效 XML文档必须有一个根元素元素,您可以在其中指定所有其他元素。另外,在文件中只能有一个元素可以存在。对XML Specification (see point 2)

一看这样,克服您的问题,你可以把你的文本文件的所有内容为一个字符串(或StringBuffer的/ StringBuilder的...),并把这个字符串<root></root>标签之间 如,

String origXML = readContentFromTextFile(fileName); 
String validXML = "<root>" + origXML + "</root>"; 
//parse validXML 

文档的格式不正确,因为你没有“根”节点:

<ROOT> 
    <DOC> 
     <TEXT> ... </TEXT> 
     ... 
    </DOC> 
    <DOC> 
     <TEXT> ... </TEXT> 
     ... 
    </DOC> 
</ROOT> 

你也很难用“标准”的XML解析器,例如Xerces的解析这一点。正如你所提到的,这个XML文档不完整,部分原因是它缺少一个XML声明<?xml version="1.0"?>,但最重要的是因为它有两个文档根(即<doc>元素)。我建议你试试TagSoup。它是为了解析(引用)“糟糕,讨厌和粗暴”的XML。没有保证,但这可能是你最好的选择。

+0

谢谢你的提示。该链接中的网站不再存在。 'TagSoup'变成了其他的链接,但很难说出什么是经典。 – smci 2017-10-13 18:11:32

您可以尝试使用xslt进行分析。

您可以创建的InputStream的子类,增加了一个前缀和后缀的输入流,并通过该类的实例以任何XML解析器:

public class EnclosedInputStream extends InputStream { 
    private enum State { 
     PREFIX, STREAM, SUFFIX, EOF 
    }; 

    private final byte[] prefix; 
    private final InputStream stream; 
    private final byte[] suffix; 
    private State state = State.PREFIX; 
    private int index; 

    EnclosedInputStream(byte [] prefix, InputStream stream, byte[] suffix) { 
     this.prefix = prefix; 
     this.stream = stream; 
     this.suffix = suffix; 
    } 

    @Override 
    public int read() throws IOException { 
     if (state == State.PREFIX) { 
      if (index < prefix.length) { 
       return prefix[index++] & 0xFF; 
      } 
      state = State.STREAM; 
     } 
     if (state == State.STREAM) { 
      int r = stream.read(); 
      if (r >= 0) { 
       return r; 
      } 
      state = State.SUFFIX; 
      index = 0; 
     } 
     if (state == State.SUFFIX) { 
      if (index < suffix.length) { 
       return suffix[index++] & 0xFF; 
      } 
      state = State.EOF; 
     } 
     return -1; 
    } 
} 
+0

为什么你需要InputStream作为构造函数中的参数?你可以使用super.read()而不是stream.read()(因为EnclosedInputStream是InputStream的子类)。 – 2011-05-10 10:46:45

+0

您不一定有权访问使用原始内容创建InputStream的代码。假设你有一个URL的例子。 – 2011-05-10 10:57:39