从流输入中解析没有根元素的 XML 片段列表

Posted

技术标签:

【中文标题】从流输入中解析没有根元素的 XML 片段列表【英文标题】:Parse a list of XML fragments with no root element from a stream input 【发布时间】:2012-06-28 22:00:18 【问题描述】:

在 Java 中使用 SAX api 是否可行?

我尝试解析这样的 XML,但得到了一个

org.xml.sax.SAXParseException: The markup in the document following the root element must be well-formed.

甚至在 endDocument 事件被触发之前。

我不想接受明显但笨拙的解决方案,例如“预先附加自定义根元素或使用缓冲片段解析”。

我正在使用 Java 1.6 的标准 SAX API。 SAX 工厂有 setValidating(false) 以防万一。

【问题讨论】:

***.com/questions/3232110/… 的副本。 可以参考Resolving "The markup in the document following the root element must be well-formed" Exception 【参考方案1】:

首先,也是最重要的一点,您正在解析的内容不是 XML 文档。 来自XML Specification:

[定义:只有一个元素,称为根,或文档元素,其任何部分都不会出现在任何其他元素的内容中。]

现在,关于用 SAX 解析这个 - 尽管你说的是笨拙 - 我建议采用以下方法:

Enumeration<InputStream> streams = Collections.enumeration(
    Arrays.asList(new InputStream[] 
        new ByteArrayInputStream("<root>".getBytes()),
        yourXmlLikeStream,
        new ByteArrayInputStream("</root>".getBytes()),
    ));

SequenceInputStream seqStream = new SequenceInputStream(streams);

// Now pass the `seqStream` into the SAX parser.

使用SequenceInputStream 是一种将多个输入流连接成单个流的便捷方式。它们将按照传递给构造函数的顺序被读取(或者在这种情况下 - 由Enumeration 返回)。

将它传递给您的 SAX 解析器,您就完成了。

【讨论】:

同意 - 笨拙地附加根元素的原因是因为您正在处理笨拙的数据。否则,一旦您关闭了您打开的第一个元素,SAX 解析器就会相信它已经完成,就像它已经完成一样。对于格式化的 XML 数据流,我也这样做 虽然你提供了一个我已经想到的答案,但实现比我想象的要优雅得多!谢谢你的回答。 嗯,SequenceInputStream 是那些早已被遗忘的实用程序之一,尽管自 Java 1.0 以来就已经存在,但似乎没人知道。只是想提醒它还在那里。 :)

以上是关于从流输入中解析没有根元素的 XML 片段列表的主要内容,如果未能解决你的问题,请参考以下文章

解析没有根元素的 XML 流

无法使用 Jackson XML 直接在根元素内反序列化列表

使用Retrofit2解析XML。多个结果列表不起作用

XDocument 读取具有名称空间的根元素的 XML 文件

在创建视图的片段期间为项目列表中的每个项目设置图像[重复]

不要在片段中显示列表视图项