使用 Java 和 UTF-8 编码生成有效的 XML

2022-09-02 12:20:43

我正在使用 JAXP 来生成和解析一个 XML 文档,从中加载一些字段是从数据库中加载的。

用于序列化 XML 的代码:

DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.newDocument();
Element root = doc.createElement("test");
root.setAttribute("version", text);
doc.appendChild(root);

DOMSource domSource = new DOMSource(doc);
TransformerFactory tFactory = TransformerFactory.newInstance();

FileWriter out = new FileWriter("test.xml");
Transformer transformer = tFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.transform(domSource, new StreamResult(out)); 

用于解析 XML 的代码:

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse("test.xml");

我遇到以下异常:

[Fatal Error] test.xml:1:4: Invalid byte 1 of 1-byte UTF-8 sequence.
Exception in thread "main" org.xml.sax.SAXParseException: Invalid byte 1 of 1-byte UTF-8 sequence.
    at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
    at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
    at javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
    at com.test.Test.xml(Test.java:27)
    at com.test.Test.main(Test.java:55)

字符串文本包括 u-元音变音符和 o-元音变音符(字符代码0xFC和0xF6)。这些是导致错误的字符。当我自己转义字符串以使用ü和 ö然后问题就消失了。当我写出 XML 时,会自动对其他实体进行编码。

如何正确编写/读取输出,而无需自己替换这些字符?

(我已经阅读了以下问题:

如何将字符从 Oracle 编码为 XML?

修复 XML 文件中的错误编码)


答案 1

使用 FileOutputStream 而不是 FileWriter。

后者应用自己的编码,几乎可以肯定不是UTF-8(根据您的平台,它可能是Windows-1252或IS-8859-1)。

编辑(现在我有时间了):

没有序幕的 XML 文档允许编码为 UTF-8 或 UTF-16。对于序言,允许指定其编码(序言只能包含 US-ASCII 字符,因此序言始终可读)。

读者处理人物;它将解码底层输入流的字节流。因此,当您将 Reader 传递给解析器时,您告诉它您已经处理了编码,因此解析器将忽略序言。当您传递 InputStream(读取字节)时,它不会做出此假设,并且会查看序言来定义编码 - 或者如果它不存在,则默认为 UTF-8/UTF-16。

我从未尝试过读取以 UTF-16 编码的文件。我怀疑解析器会寻找字节顺序标记(BOM)作为文件的前2个字节。


答案 2

好吧,当然,并且不是有效的字符。这些应该已与两个字节序列一起:和 。0xFC0xF6UTF-80x3CBC0x3CB6

最有可能的问题是字符的原始来源被定义为当它们不是时。UTF-8


推荐