成功进行编组后无法解组 \u0000

11

我有一个包含二进制0的UTF-8字符串("A\u0000B")。JAXB可以很好地将包含这种字符的XML文档编组,但无法对其进行解组:

final JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
final Marshaller marshaller = jaxbContext.createMarshaller();
final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

Root root = new Root();
root.value = "A\u0000B";

final ByteArrayOutputStream os = new ByteArrayOutputStream();
marshaller.marshal(root, os);

unmarshaller.unmarshal(new ByteArrayInputStream(os.toByteArray()));

根类非常简单:
@XmlRootElement
class Root { @XmlValue String value; }

输出的XML文件在AB之间包含二进制0(十六进制表示为41 00 42),这会导致在取消编组过程中出现以下错误:

org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 63; 
An invalid XML character (Unicode: 0x0) was found in the element content of the document.

有趣的是,使用原始DOM API(example)会产生转义的0A�B,但尝试读取它会产生类似的错误。此外,任何XML解析器或xmllint都不允许使用0(既不是二进制也不是转义)(另请参见:Python + Expat:�实体出错)。

我的问题:

但是,Java中成熟的XML堆栈(我正在使用1.7.0_05)不应该默认处理这个问题或者有一些简单的设置吗?我正在寻找转义、忽略或快速失败的方法,但是生成无效的XML的默认行为是不可接受的。我相信这样基本的功能不应该需要客户端额外编码。


最近我编写了一些测试用例来测试我处理“无效的XML字符(Unicode:0x0)”场景的能力。如果我知道我实际上可以使用Marshaller注入null(而不是直接编辑字符串),我的生活会更轻松,但我怀疑这不是原因。 - matt freake
请参见https://dev59.com/8m025IYBdhLWcg3wwYz4。 - Catchwa
1个回答

3
为什么JAXB/DOM API 允许创建无法读回的无效XML文档?在编组期间不应该快速失败吗?
你需要问实现者。他们可能认为检查每个数据字符的序列化开销不值得…特别是如果解析器接下来要再次检查它们。一旦决定采用这种方式实现序列化程序(或者只是出于错误而这样做),如果他们随后更改了默认情况下进行严格检查的行为,则会破坏依赖于能够序列化非法XML的现有代码。
但成熟的Java XML堆栈(我使用的是1.7.0_05)不应该通过默认方式或具有某些简单设置来处理此问题吗?
如果您接受上述原因#2,则不一定。即使是简单的设置也可能对性能产生可衡量的影响。
此外,任何XML解析器或xmllint都不允许使用0(既不二进制也不转义)...
是的! 这是XML规范所禁止的。
但是,一个更有趣的测试是看看当您尝试使用其他XML堆栈生成包含非法字符的XML时会发生什么。
有一种优雅和全局的解决方案吗?
如果您尝试解决的问题是如何发送\u0000\u000B,则需要在将其插入DOM之前对字符串应用某些特定于应用程序的编码。 另一端需要部署等效解码。
如果您尝试解决的问题是如何在为时已晚之前检测到坏数据,则可以使用序列化器和最终输出流之间的输出流过滤器来实现。 但是,如果检测到错误,则没有很好的(即对XML使用者透明)方法来修复它。

2
序列化器必须检查每个字符是否需要转义(例如 '<','&'),因此添加一个额外的(可配置的)检查空字符的步骤对性能影响不大。 - jarnbjo
1
阅读我的第一个答案。询问实现者! - Stephen C
1
感谢您的详细回复。我无法相信性能会是一个问题,但这很难回答,同意吧。然而,我不同意关闭这个问题,认为它“没有建设性”。我不仅仅是在问“为什么?”(我认为有一些记录的原因 - 在哪里,答案可能非常具有建设性),而且还在问如何解决这个问题或绕过这个行为。无论如何,还是谢谢。 - Tomasz Nurkiewicz
1
我投票关闭的原因是像这样的问题:“为什么JAXB / DOM API允许创建无法读回的无效XML文档?在编组期间不应该快速失败吗?”和“但是成熟的Java XML堆栈(我正在使用1.7.0_05)不应该默认处理此问题或具有某些简单的设置吗?”这些问题显然没有客观可答复的答案...并且(在我看来)是非建设性辩论的邀请。 - Stephen C

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接