java xml 多个根元素_关于java:解析没有根元素的XML流

我需要解析一个连续的格式良好的XML元素流,只给我一个已经构造好的java.io.Reader对象。这些元素没有包含在根元素中,也没有用像"这样的XML头作为前缀,但在其他方面是有效的XML。

使用JavaEDCX1的2个类不起作用,因为XML读取器期望解析封闭格式的XML,从封闭的根元素开始。所以,它只读取流中的第一个元素,它将其视为根,并在下一个元素中失败,典型的

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

对于不包含根元素的文件,但如果该元素确实存在或可以定义(并称为myrootelement),则可以执行以下操作:

Strint path = ;

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

StringBuilder buffer = new StringBuilder();

buffer.append("<?xml version="1.0"?>

");

buffer.append(");

buffer.append("[

buffer.append(path);

buffer.append("">]>

");

buffer.append("

");

buffer.append("&data;

");

buffer.append("

");

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

xmlReader.parse(source);

我已经通过将部分java.io.Reader输出保存到一个文件中来测试了上面的内容,它可以工作。但是,这种方法在我的例子中不适用,并且不能插入这样的额外信息(XML头、根元素),因为传递给我的代码的java.io.Reader对象已经被构造出来了。

本质上,我在寻找"零碎的XML解析"。所以,我的问题是,是否可以使用标准的Java API(包括EDCOX1的5)和EDCOX1(6个)包来完成?

您可以引用解析"根元素后面的文档中的标记必须格式正确"异常

Sequenceinputstream来救援:

SAXParserFactory saxFactory = SAXParserFactory.newInstance();

SAXParser parser = saxFactory.newSAXParser();

parser.parse(

new SequenceInputStream(

Collections.enumeration(Arrays.asList(

new InputStream[] {

new ByteArrayInputStream("".getBytes()),

new FileInputStream(file),//bogus xml

new ByteArrayInputStream("".getBytes()),

}))

),

new DefaultHandler()

);

您可以将给定的Reader包装在一个FilterReader子类中,您可以实现该子类来或多或少地完成您在这里所做的工作。

编辑:

虽然这与执行您自己的Reader委托给由其他几个答案给出的Reader对象的提议类似,但几乎FilterReader中的所有方法都必须被重写,因此使用超类可能不会获得太多好处。

其他提议的一个有趣的变化可能是实施一个SequencedReader,它包含多个Reader对象,并在一个对象用完时按顺序切换到下一个对象。然后,您可以传入一个StringReader对象,其中包含要添加的根的开始文本、原始Reader和另一个带有结束标记的StringReader。

您可以编写自己的读卡器实现来封装给定的读卡器实例。这个新的阅读器应该像您在示例代码中所做的那样,提供头和根元素,然后提供来自底层阅读器的数据,最后提供结束根标记。通过这种方式,您可以向XML解析器提供有效的XML流,还可以使用传递给代码的reader对象。

+一个伟大的思想是相似的(尽管我比你早一分钟就想到了这一点)。

+给你们两个。直接实现一个读卡器可能比在我的响应中尝试对filterreader进行子类化要好。

您可以创建自己的读卡器,将其委托给提供的读卡器,如下所示:

final Reader reader = ;

Reader wrappedReader = new Reader()

{

Reader readerCopy = reader;

String start ="<?xml version="1.0"?>";

String end ="";

int index;

@Override

public void close() throws IOException

{

readerCopy.close();

}

@Override

public int read(char[] cbuf, int off, int len) throws IOException

{

// You'll have to get the logic right here - this is only placeholder code

if (index < start.length())

{

// Copy from start to cbuf

}

int result = readerCopy.read(cbuf, off, len);

if (result == -1) {

// Copy from end

}

index += len;

return result;

}

};

你必须填写逻辑,首先从start中读取,然后在中间委托给读卡器,最后当读卡器为空时,从end中读取。

不过,这种方法是可行的。

但是否真的有任何XML解析类可以读取"碎片化"的XML?

只需插入虚拟根元素。我能想到的最优雅的解决方案是创建自己的inputstream或reader,当您第一次调用它的read()/readline()时,它包装常规inputsteam/reader并返回虚拟的,然后返回有效负载流的结果。这应该满足SAX解析器。

答案3是可行的,但对我来说,我必须从Sequenceinputstream创建一个inputsource的额外步骤。

XMLReader xmlReader = saxParser.getXMLReader();

xmlReader.setContentHandler((ContentHandler) this);

// Trying to add root element

Enumeration streams = Collections.enumeration(

Arrays.asList(new InputStream[] {

new ByteArrayInputStream("".getBytes()),

new FileInputStream(xmlFile),//bogus xml

new ByteArrayInputStream("".getBytes()),

}));

InputSource is = new InputSource(seqStream);

xmlReader.parse(is);

通常答案是重新排序的,所以"答案3"是相对的,你的意思是什么?

我指的是用户656449给出的答案

不编译-请注意,没有在任何地方定义"seqstream",重命名为stream会为新的inputsource生成"不合适的构造函数"错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值