我有以下方法将 XMLDom 写入流:
public void writeToOutputStream(Document fDoc, OutputStream out) throws Exception {
fDoc.setXmlStandalone(true);
DOMSource docSource = new DOMSource(fDoc);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "no");
transformer.transform(docSource, new StreamResult(out));
}
我正在测试其他一些 XML 功能,这只是我用来写入文件的方法。我的测试程序生成了 33 个测试用例,其中文件被写出。其中 28 个具有以下标题:
<?xml version="1.0" encoding="UTF-8"?>...
但由于某种原因,现在有 1 个测试用例产生:
<?xml version="1.0" encoding="ISO-8859-1"?>...
还有四种产品:
<?xml version="1.0" encoding="Windows-1252"?>...
如您所见,我将 ENCODING 输出键设置为 UTF-8。这些测试用于在早期版本的 Java 上工作。我已经有一段时间(一年多)没有运行测试了,但是今天在“Java(TM) SE 运行时环境(build 1.6.0_22-b04)”上运行我得到了这个有趣的行为。
我已经验证导致问题的文档是从最初具有这些编码的文件中读取的。似乎新版本的库正在尝试保留已读取源文件的编码。但这不是我想要的……我真的希望输出为 UTF-8。
有谁知道可能导致转换器忽略 UTF-8 编码设置的任何其他因素?为了忘记最初读取的文件的编码,是否需要在文档上设置其他任何内容?
更新:
我在另一台机器上检查了同一个项目,在那里构建并运行了测试。在那台机器上,所有的测试都通过了!所有文件的标题中都有“UTF-8”。该机器具有“Java(TM) SE Runtime Environment (build 1.6.0_29-b11)” 两台机器都运行 Windows 7。在正常工作的新机器上,jdk1.5.0_11 用于构建,但在旧机器上机器 jdk1.6.0_26 用于构建。用于两个构建的库完全相同。会不会是 JDK 1.6 在构建时与 1.5 不兼容?
更新:
4.5年后,Java库仍然坏掉,但由于下面Vyrx的建议,我终于有了一个合适的解决方案!
public void writeToOutputStream(Document fDoc, OutputStream out) throws Exception {
fDoc.setXmlStandalone(true);
DOMSource docSource = new DOMSource(fDoc);
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.INDENT, "no");
out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>".getBytes("UTF-8"));
transformer.transform(docSource, new StreamResult(out));
}
解决方案是禁用标头的写入,并在将 XML 序列化到输出流之前写入正确的标头。蹩脚,但它产生正确的结果。4 年前打破的测试现在再次运行!