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

Java 如何在一个文档中解析多个连续的xml文件?,java,xml,xml-parsing,Java,Xml,Xml Parsing,我有一个大文本文件,它是一系列XML有效文档,如下所示: <DOC> <TEXT> ... </TEXT> ... </DOC> <DOC> <TEXT> ... </TEXT> ... </DOC> ... ... ... ... 等等。没有,分隔每个单独的xml。在Java中解析并获取每个中下的值的最佳方法是什么 如果我将整个过程传递给DocumentBui

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

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

... 
...
... 
...
等等。没有
分隔每个单独的xml。在Java中解析并获取每个
下的值的最佳方法是什么


如果我将整个过程传递给DocumentBuilder,我会收到一个错误,说明文档格式不正确。有没有比简单地遍历一个字符串更好的解决方案,为每个
构建一个字符串?

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

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

... 
...
... 
...

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

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

... 
...
... 
...

您将很难使用“标准”XML解析器(如Xerces)对此进行解析。正如您所提到的,此XML文档的格式不好,部分原因是它缺少XML声明
,但最重要的原因是它有两个文档根(即
元素)


我建议你试试。它的目的是解析(引用)“糟糕、恶劣和野蛮”的XML。不保证,但这可能是您的最佳选择。

您将很难使用“标准”XML解析器(如Xerces)对此进行解析。正如您所提到的,此XML文档的格式不好,部分原因是它缺少XML声明
,但最重要的原因是它有两个文档根(即
元素)


我建议你试试。它的目的是解析(引用)“糟糕、恶劣和野蛮”的XML。不保证,但这可能是您的最佳选择。

有效的XML文档必须有一个根元素,您可以在该根元素下指定所有其他元素。此外,文档中只能存在一个根元素。看看

因此,为了解决您的问题,您可以将文本文件的所有内容放入一个字符串(或StringBuffer/StringBuilder…)中,并将该字符串置于
标记之间 e、 g,

String origXML=readContentFromTextFile(文件名);
字符串validXML=“”+origXML+”;
//解析validXML

有效的XML文档必须有一个根元素,您可以在该根元素下指定所有其他元素。此外,文档中只能存在一个根元素。看看

因此,为了解决您的问题,您可以将文本文件的所有内容放入一个字符串(或StringBuffer/StringBuilder…)中,并将该字符串置于
标记之间 e、 g,

String origXML=readContentFromTextFile(文件名);
字符串validXML=“”+origXML+”;
//解析validXML

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

您可以尝试使用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;
    }
}
public类封闭的InputStream扩展了InputStream{
私有枚举状态{
前缀、流、后缀、EOF
};
私有最终字节[]前缀;
私有最终输入流;
私有最终字节[]后缀;
私有状态State=State.PREFIX;
私有整数索引;
封闭的输入流(字节[]前缀,输入流,字节[]后缀){
this.prefix=前缀;
this.stream=流;
this.suffix=后缀;
}
@凌驾
public int read()引发IOException{
if(state==state.PREFIX){
如果(索引<前缀长度){
返回前缀[index++]&0xFF;
}
state=state.STREAM;
}
if(state==state.STREAM){
int r=stream.read();
如果(r>=0){
返回r;
}
state=state.SUFFIX;
指数=0;
}
if(state==state.SUFFIX){
如果(索引<后缀长度){
返回后缀[index++]&0xFF;
}
state=state.EOF;
}
返回-1;
}
}

您可以创建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;
    }
}
public类封闭的InputStream扩展了InputStream{
私有枚举状态{
前缀、流、后缀、EOF
};
私有最终字节[]前缀;
私有最终输入流;
私有最终字节[]后缀;
私有状态State=State.PREFIX;
私有整数索引;
封闭的输入流(字节[]前缀,输入流,字节[]后缀){
this.prefix=前缀;
this.stream=流;
this.suffix=后缀;
}
@凌驾
public int read()引发IOException{
if(state==state.PREFIX){
如果(索引<前缀长度){
返回前缀[index++]&0xFF;
}
state=state.STREAM;
}
if(state==state.STREAM){
int r=stream.read();
如果(r>=0){
返回r;
}
state=state.SUFFIX;
指数=0;
}
if(state==state.SUFFIX){
如果(索引<后缀长度){
返回后缀[index++]&0xFF;
}
state=state.EOF;
}
返回-1;
}
}

为什么需要InputStream作为构造函数中的参数?您可以使用super.read()而不是stream.read()(因为EnclosedInputStream是InputStream的子类)。您不必访问使用原始内容创建InputStream的代码。例如,假设您有一个URL,为什么需要InputStream作为构造函数中的参数?您可以使用super.read()而不是stream.read()(因为EnclosedInputStream是InputStream的一个子类)