我有一个包含二进制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文件在A
和B
之间包含二进制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)会产生转义的0
:A�B
,但尝试读取它会产生类似的错误。此外,任何XML解析器或xmllint
都不允许使用0
(既不是二进制也不是转义)(另请参见:Python + Expat:�实体出错)。
我的问题:
JAXB/DOM API为什么允许创建无法读取的无效XML文档?在编组期间不应该快速失败吗?
是否有一种优雅且全局的解决方案?我看到人们通过以下方法解决这个问题:
但是,Java中成熟的XML堆栈(我正在使用1.7.0_05)不应该默认处理这个问题或者有一些简单的设置吗?我正在寻找转义、忽略或快速失败的方法,但是生成无效的XML的默认行为是不可接受的。我相信这样基本的功能不应该需要客户端额外编码。