解析XML中的垂直制表符编码字符

时间:2017-02-21 04:37:42

标签: java xml parsing dom

我正在处理从输入生成XML的遗留系统。此输入有时包含垂直制表符控制字符。然后,这些字符将在生成的XML中进行编码。垂直选项卡可以用\u000B的Java字符串编写。这是一个示例代码,说明了发生了什么(原始进程从输入中获取字符串,并创建没有任何预处理的文本节点):

    DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
    Document doc = documentBuilder.parse(new InputSource(new StringReader("<xml></xml>")));
    Element sample = doc.createElement("sample");
    sample.appendChild(doc.createTextNode("Hello\u000BWorld"));
    doc.getDocumentElement().appendChild(sample);

    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer transformer = tf.newTransformer();
    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
    transformer.setOutputProperty(OutputKeys.METHOD, "xml");
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
    transformer.transform(new DOMSource(doc), new StreamResult(new OutputStreamWriter(System.out, "UTF-8")));

这会生成一个无效的XML文档:

<?xml version="1.0" encoding="UTF-8"?><xml>
    <sample>Hello&#11;World</sample>
</xml>

现在我需要使用相同的解析器,即:

DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document doc = documentBuilder.parse(new InputSource(new StringReader(theResultFromAbove)));

再次生成Document实例。但这失败了:

[Fatal Error] :2:23: Character reference "&#
org.xml.sax.SAXParseException; lineNumber: 2; columnNumber: 23; Character reference "&#
    at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:257)

我可以控制第二个解析器,因此我可以在解析输出之前搜索并替换&#11;。我还首先控制了生成XML的代码,因此我可以在所有这些发生之前删除垂直选项卡。

然而,我可以做些什么来添加实现 &#11;实体,这样解析器不仅可以对其进行编码,还可以对其进行正确解码?

1 个答案:

答案 0 :(得分:3)

不确定这是否适合您,但将XML版本从1.0更改为1.1会打开有效字符列表以包含除0x00以外的所有控制字符,从而使文档包含0x0B }或VT有效。

要将版本设置为1.1,请将以下配置添加到转换器:

transformer.setOutputProperty(OutputKeys.VERSION, "1.1");