我即时创建XML字符串(不读取文件)。然后我使用Cocoon 3通过FOP将其转换为PDF。在中间某处的Xerces运行。当我使用硬编码的东西时,一切正常。一旦我将德语变音符号放入数据库并使用该数据丰富我的xml,我得到:
Caused by: org.apache.cocoon.pipeline.ProcessingException: Can't parse the XML string.
at org.apache.cocoon.sax.component.XMLGenerator$StringGenerator.execute(XMLGenerator.java:326)
at org.apache.cocoon.sax.component.XMLGenerator.execute(XMLGenerator.java:104)
at org.apache.cocoon.pipeline.AbstractPipeline.invokeStarter(AbstractPipeline.java:146)
at org.apache.cocoon.pipeline.AbstractPipeline.execute(AbstractPipeline.java:76)
at de.grobmeier.tab.webapp.modules.documents.InvoicePipeline.generateInvoice(InvoicePipeline.java:74)
... 87 more
Caused by: com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: Invalid byte 1 of 1-byte UTF-8 sequence.
at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.invalidByte(UTF8Reader.java:684)
at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.read(UTF8Reader.java:554)
然后我调试了我的应用程序并发现,我的“Ä”(数据库来自数据库)的字节值为196,即十六进制的C4。这就是我所期望的:http://www.utf8-zeichentabelle.de/
我不知道为什么我的代码失败了。
然后我尝试手动添加BOM,如:
byte[] bom = new byte[3];
bom[0] = (byte) 0xEF;
bom[1] = (byte) 0xBB;
bom[2] = (byte) 0xBF;
String myString = new String(bom) + inputString;
我知道这不是很好,但我尝试过 - 当然失败了。我试图在前面添加一个xml标题:
<?xml version="1.0" encoding="UTF-8"?>
哪个也失败了。然后我把它结合起来。失败。
毕竟我尝试过类似的东西:
xmlInput = new String(xmlInput.getBytes("UTF8"), "UTF8");
实际上什么都没做,因为它已经是UTF-8了。它仍然失败。
那么......任何想法我做错了什么以及Xerces对我的期待是什么?
由于 基督教
答案 0 :(得分:13)
如果您的数据库只包含一个字节(值为0xC4),那么您不使用UTF-8编码。
字符“LATIN CAPITAL LETTER A WITH DIAERESIS”具有代码点值U + 00C4,但UTF-8不能在单个字节中对其进行编码。如果你在UTF8-zeichentabelle.de上查看第三列“UTF-8(十六进制)”,你会看到UTF-8将其编码为0xC3 84(两个字节)。
请阅读Joel的文章“The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)”以获取更多信息。
XMLGenerator
类,那么在SAX解析期间会出现问题导致此混乱。
我looked up the code找到Cocoon-stax中的实际问题:
if (XMLGenerator.this.logger.isDebugEnabled()) {
XMLGenerator.this.logger.debug("Using a string to produce SAX events.");
}
XMLUtils.toSax(new ByteArrayInputStream(this.xmlString.getBytes()), XMLGenerator.this.getSAXConsumer();
如您所见,调用getBytes()
将创建一个带有JRE默认编码的Byte数组,然后无法解析。这是因为XML声明自己是UTF-8,而数据现在再次以字节为单位,并且可能使用Windows代码页。
作为一种解决方法,可以使用以下内容:
new org.apache.cocoon.sax.component.XMLGenerator(xmlInput.getBytes("UTF-8"),
"UTF-8");
这将触发正确的内部动作(正如Christian通过试验API发现的那样)。
我在Apache的bug追踪器中opened an issue。
编辑2:问题已修复,将包含在即将发布的版本中。
答案 1 :(得分:2)
您在该页面上看到的C4
是指unicode代码点U+00C4
。用于表示UTF-8中的这种代码点的字节序列不是"\xC4"
。你想要的是UTF-8(十六进制)列中的内容,即"\xC3\x84"
。
因此,您的数据不是UTF-8。
您可以阅读有关如何使用UTF-8 here编码数据的方法。
答案 2 :(得分:0)
我正在使用TextPad作为文本编辑器运行Windows 7,以手动构建xml数据文件。我得到了MalformedByteSequenceException
。我在xml文件中的规范是UTF-8。在探索之后,我发现我的编辑器有一个工具“工具...转换为DOS”。我这样做了,重新保存了文件,异常消失了,我的代码运行正常。
然后我在编辑器中查看了该文件类型的默认编码。它是ASCII,但是当我将xml编码参数更改为ASCII时,我得到另一个不同的MalformedByteSequenceException
。
因此,在Windows系统上,您可以尝试将xml编码保持为UTF-8,但保存编码的DOS文件。我没有进一步深入研究为什么这样做。