分析不带根元素的 XML 流

2022-09-03 00:02:58

我需要解析一个格式正确的XML元素的连续流,我只得到了一个已经构造的对象。这些元素不包含在根元素中,也不在前面附加 XML 标头(如 ),但在其他方面是有效的 XML。java.io.Reader<?xml version="1.0"?>"

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

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);

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

从本质上讲,我正在寻找“碎片化的XML解析”。所以,我的问题是,可以使用标准的Java API(包括和包)来完成吗?org.sax.xml.*java.xml.*


答案 1

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()
    );

答案 2

你可以将你的给定包装在你实现的子类中,以或多或少地完成你在这里做的事情。ReaderFilterReader

编辑:

虽然这类似于实现你自己的委托给其他几个答案给出的给定对象的建议,但几乎所有的方法都必须被覆盖,所以你可能不会从使用超类中获得太多好处。ReaderReaderFilterReader

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


推荐