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

时间:2011-05-10 06:28:26

标签: java xml xml-parsing

我有一个大文本文件,它是一系列XML有效文档,如下所示:

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

等。没有<?xml version="1.0"><DOC></DOC>分隔每个单独的xml。在Java中解析此问题的最佳方法是什么,并在每个<TEXT>中获取<DOC>下的值?

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

5 个答案:

答案 0 :(得分:5)

有效 XML文档必须具有 root 元素,您可以在其下指定所有其他元素。此外,在文档中只能存在一个 root 元素。看看XML Specification (see point 2)

因此,为了克服您的问题,您可以将文本文件的所有内容转换为String(或StringBuffer / StringBuilder ...)并将此字符串放在<root></root>标记之间 例如,

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

答案 1 :(得分:2)

由于您没有“根”节点,因此文档格式不正确:

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

答案 2 :(得分:1)

使用“标准”XML解析器(如Xerces)解析此问题很困难。正如您所提到的,XML文档的格式不正确,部分原因是它缺少XML声明<?xml version="1.0"?>,但最重要的是因为它有两个文档根(即<doc>元素)。

我建议你试试TagSoup。它打算解析(引用)“糟糕,讨厌和野蛮”的XML。不保证,但这可能是你最好的镜头。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

您可以创建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;
    }
}