我有一个InputStream或String,里面有两个xmls,如下所示:
<?xml version="1.0" standalone="yes"?>
<items
blahblahblah1
</items>
<?xml version="1.0" standalone="yes"?>
<items
blahblahblah2
</items>
它们具有相同的格式但数据不同。我想解析它们,但由于这不是有效的xml,我需要找到一种方法来拆分它们。
唯一可以想到的是字符串操作:
<?xml version="1.0 standalone="yes"?>
<?xml version="1.0 standalone="yes"?>
行,并用<ROOT> </ROOT>
包围剩余部分以生成一个有效的xml,并弄清楚如何从那里解析然而,这两种方法都看似hacky和低效。还有更好的方法吗?
答案 0 :(得分:1)
这是一个糟糕的设计,因为字符串"<?xml"
可以合法地出现在CDATA部分或评论中。但是你只需要冒险尝试,并且在你看到"<?xml"
出现的时候拆分文件,希望是最好的,并且如果错误提出了这个想法,那就责怪谁。唯一的选择是为这个XML变体编写自己的解析器,这不会太有趣。
答案 1 :(得分:1)
我在这里提出的任何建议都没有经过测试,但这些是我认为我会采取的路线。
如果预计响应长度很小,我个人可能只是按照您的建议将连接的XML响应放入String
,然后使用标准String
方法提取单独的XML文档,或,如您所建议的那样,删除XML声明字符串并用一对根元素包装整个批次。这取决于您是想用单个文档还是多个文档提供XML解析器。我很久没有处理BasicHttpResponse
,但我认为你可以使用InputStream
得到mBasicHttpResponse.getEntity().getContent()
响应实体,然后使用其中一种方法获得String
InputStream
1}}来自InputStream
。
另一方面,如果我希望处理相当冗长的数据,或者如果响应实体可能包含不确定数量的连接XML文档,那么我会考虑使用自定义{包装获取的InputStream
。 {1}}或Reader
执行(a)剥离声明和(b)插入新的根元素。除了他没有要处理的声明之外,SO上有其他人就你面临的问题提出了一个非常相似的问题here。查看user656449的答案,我们看到了如何在将InputStream
包含一些虚拟根元素之前将其传递给SAX解析器的建议:
(公开复制自引用的SO问题/答案):
SAXParserFactory saxFactory = SAXParserFactory.newInstance();
SAXParser parser = saxFactory.newSAXParser();
parser.parse(
new SequenceInputStream(
Collections.enumeration(Arrays.asList(
new InputStream[] {
new ByteArrayInputStream("<dummy>".getBytes()),
new FileInputStream(file),//bogus xml
new ByteArrayInputStream("</dummy>".getBytes()),
}))
),
new DefaultHandler()
);
但另外在这种情况下,您可以用自己创建的某种FileInputStream
替换CustomFilterFileInputStream
来执行声明行的剥离。您的CustomFilterFileInputStream
将围绕从InputStream
获得的BasicHttpResponse
,然后使用SequenceInputStream
添加新的根标记。
如果您真的 以这种方式接受XML数据,并且如果您希望在单个响应中处理大量数据,那么我认为您需要这样做的方向。