自Java 9版本起,javax.xml.transform.Transformer
和OutputKeys.INDENT
对CDATA标签的处理方式发生了变化。简而言之,在Java 8中,一个包含字符数据的名为'test'的标签会导致以下结果:
<test><![CDATA[data]]></test>
但是使用Java 9则会产生相同的结果
<test>
<![CDATA[data]]>
</test>
这并不是相同的XML。
我曾经从一份已失效的资料中了解到,Java 9 可以使用 DocumentBuilderFactory
并设置 setIgnoringElementContentWhitespace=true
来解决此问题,但在 Java 11 中无法使用。
有人知道如何在Java 11中处理此问题吗?我要么寻找一种方法来防止额外的换行符(但仍然能够格式化我的XML),要么能够在解析XML时忽略它们(最好使用SAX)。
不幸的是,我不知道CDATA标记在我的应用程序中实际包含什么。它可能以空格或换行符开头或结尾,因此我不能在读取XML时只是删除它们,也不能在生成的对象中实际设置该值。
演示此问题的示例程序:
public static void main(String[] args) throws TransformerException, ParserConfigurationException, IOException, SAXException
{
String data = "data";
StreamSource source = new StreamSource(new StringReader("<foo><bar><![CDATA[" + data + "]]></bar></foo>"));
StreamResult result = new StreamResult(new StringWriter());
Transformer tform = TransformerFactory.newInstance().newTransformer();
tform.setOutputProperty(OutputKeys.INDENT, "yes");
tform.transform(source, result);
String xml = result.getWriter().toString();
System.out.println(xml); // I expect bar and CDATA to be on same line. This is true for Java 8, false for Java 11
Document document = DocumentBuilderFactory.newInstance()
.newDocumentBuilder()
.parse(new InputSource(new StringReader(xml)));
String resultData = document.getElementsByTagName("bar")
.item(0)
.getTextContent();
System.out.println(data.equals(resultData)); // True for Java 8, false for Java 11
}
编辑:供后续参考,我已向Oracle提交了一个缺陷报告,并在Java 14中修复了此问题:https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8223291