成功编组后无法取消编组\ u0000

Tom*_*icz 9 java xml unicode jaxb

我在UTF-8()里面有一个String控制二进制文件.JAXB愉快地编组包含此类字符的XML文档,但后来无法解组它:0"A\u0000B"

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

根类很简单:

@XmlRootElement
class Root { @XmlValue String value; }
Run Code Online (Sandbox Code Playgroud)

输出XML包含二进制0以及之间AB(十六进制: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.
Run Code Online (Sandbox Code Playgroud)

有趣的是,使用原始DOM API(示例)会产生转义0:A�B但尝试将其读回会产生类似的错误.也0(均未二进制也不转义)不被任何XML解析器允许或xmllint(还参见:Python的+外籍:错误�实体).

我的问题:

但是,不应该在Java(我使用1.7.0_05)成熟的XML堆栈默认处理或通过一些简单的设置?我正在寻找逃避,忽略或快速失败 - 但生成无效XML的默认行为是不可接受的.我相信这样的基本功能不应该在客户端需要任何额外的编码.

Ste*_*n C 3

为什么 JAXB/DOM API 允许创建无法读回的无效 XML 文档?在编组过程中它不应该快速失败吗?

  1. 您需要询问实施者。

  2. 他们可能认为检查每个序列化数据字符的费用是不合理的......特别是如果解析器随后要再次检查它们。

  3. 决定以这种方式实现序列化程序(或者只是错误地这样做)后,如果他们随后更改行为以默认进行严格检查,则会破坏依赖于能够序列化非法 XML 的现有代码。

但是,Java 中成熟的 XML 堆栈(我使用的是 1.7.0_05)不应该默认处理这个问题还是通过一些简单的设置来处理这个问题?

不一定……如果您接受上面的原因#2。即使是简单的设置也可能对性能产生可衡量的影响。


此外,任何 XML 解析器或 xmllint 都不允许 0(既不是二进制也不是转义)...

确实如此!XML 规范禁止这样做。

然而,更有趣的测试是看看当您尝试使用其他 XML 堆栈生成包含非法字符的 XML 时会发生什么。


有一些优雅且全球性的解决方案吗?

如果您要解决的问题是如何发送 or \u0000\u000B那么您需要在将字符串插入 DOM之前对字符串应用一些特定于应用程序的编码。另一端需要部署等效的解码。

如果您试图解决的问题是如何在为时已晚之前检测到坏数据,您可以在序列化器和最终输出流之间使用输出流过滤器来实现此目的。但是,如果您检测到不良情况,则没有好的(即对 XML 使用者透明的)方法来修复它。

  • 序列化器必须检查每个字符是否必须转义(例如“<”、“&”),因此为空字符添加额外的(可配置的)检查不会对性能产生太大影响。 (2认同)