解析没有根元素的XML流

PNS*_*PNS 17 java xml sax xmlreader

我需要解析连续的格式良好的XML元素流,我只给它一个已构造的java.io.Reader对象.这些元素不包含在根元素中,也不是像XML标题一样<?xml version="1.0"?>",而是有效的XML.

使用Java org.xml.sax.XMLReader类不起作用,因为XML Reader期望从封闭的根元素开始解析格式良好的XML.因此,它只读取流中的第一个元素,它将其视为根,并在下一个元素中失败,典型的

org.xml.sax.SAXParseException:根元素后面的文档中的标记必须格式正确.

对于不包含根元素的文件,但是这样的元素确实存在或者可以定义(并且被称为MyRootElement),可以执行以下操作:

        Strint path = <the full path to the file>;

        XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();

        StringBuilder buffer = new StringBuilder();

        buffer.append("<?xml version=\"1.0\"?>\n");
        buffer.append("<!DOCTYPE MyRootElement ");
        buffer.append("[<!ENTITY data SYSTEM \"file:///");
        buffer.append(path);
        buffer.append("\">]>\n");
        buffer.append("<MyRootElement xmlns:...>\n");
        buffer.append("&data;\n");
        buffer.append("</MyRootElement>\n");

        InputSource source = new InputSource(new StringReader(buffer.toString()));

        xmlReader.parse(source);
Run Code Online (Sandbox Code Playgroud)

我已经通过将部分java.io.Reader输出保存到文件来测试上述内容并且它可以工作.但是,这种方法在我的情况下不适用,并且无法插入此类额外信息(XML标头,根元素),因为java.io.Reader已经构造了传递给我的代码的对象.

基本上,我正在寻找"碎片式XML解析".所以,我的问题是,可以使用标准Java API(包括org.sax.xml.*java.xml.*包)来完成吗?

use*_*449 14

SequenceInputStream来救援:

    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()
    );
Run Code Online (Sandbox Code Playgroud)


Don*_*oby 9

您可以将您的给定包装ReaderFilterReader您实现的子类中,以便在此处执行更多或更少的操作.

编辑:

虽然这是类似于实现自己的提议Reader委托给定Reader其他几个答案给定的对象,几乎在所有的方法FilterReader都必须重写,因此您可能无法使用超多的收获.

其他提议的一个有趣的变化可能是实现一个SequencedReader包装多个Reader对象并在一个用完时移动到序列中的下一个对象.然后,您可以传入一个StringReader对象,其中包含要添加的根的起始文本,原始文本Reader和另一个StringReader带有结束标记的文本.


phl*_*tos 5

您可以编写自己的Reader-Implementation来封装您给出的Reader实例.这个新的Reader应该只是你在你的示例代码中做的事情,提供标题和根元素,然后是底层读者的数据,最后是结束的根标记.通过这种方式,您可以向XML解析器提供有效的XML流,您也可以使用传递给代码的Reader对象.