使用Java将XML文档从Latin1转换为UTF8
我正在尝试创建一个XML文档(rss提要),并且已经解决了其中的所有问题,除了一个字符编码问题。问题是我使用的是UTF-8编码,就像这样使用Java将XML文档从Latin1转换为UTF8,java,xml,character-encoding,Java,Xml,Character Encoding,我正在尝试创建一个XML文档(rss提要),并且已经解决了其中的所有问题,除了一个字符编码问题。问题是我使用的是UTF-8编码,就像这样,除了文档本身没有编码为UTF-8之外 我正在使用org.apache.ecs.xml包创建所有标记。然后我使用doc.output(stream)来编写内容。这种方法似乎不使用UTF-8编写输出,我不知道如何实现这一点。在我这么做之前,一些符号(我第一次注意到的是英镑)在大多数读者中并没有得到正确的呈现 --更新了更多信息-- 我最终使用了一个糟糕的解决方案(
,除了文档本身没有编码为UTF-8之外
我正在使用org.apache.ecs.xml包创建所有标记。然后我使用doc.output(stream
)来编写内容。这种方法似乎不使用UTF-8编写输出,我不知道如何实现这一点。在我这么做之前,一些符号(我第一次注意到的是英镑)在大多数读者中并没有得到正确的呈现
--更新了更多信息--
我最终使用了一个糟糕的解决方案(如评论中所解释的)来解决这个问题。正确答案似乎是不要使用org.apache.ecs.xml库。谢谢大家的帮助。StackOverflow再次获胜。我不熟悉此软件包,但从网上的来源来看,我怀疑它可能已损坏: 包含像这样的内容
for (int i=0; i<prolog.size(); i++) {
268 ConcreteElement e = (ConcreteElement)prolog.elementAt(i);
269 e.output(out);
270 // XXX really this should use line separator!
271 // XXX should also probably check for pretty print
272 // XXX also probably have difficulties with encoding
for(int i=0;i这是我编写的一个函数,用于将所有非ASCII字符转换为相应的实体。可能有助于在输出前清理某些PCDATA内容
/**
* Creates xml entities for non ascii characters in the given String.
*/
public static String xmlEntitify(String in){
StringBuffer b = new StringBuffer();
for (int i=0;i<in.length();i++){
Character c = in.charAt(i);
if (c<128){
b.append(c);
}
else if (c=='\ufeff'){
// BOM character, just remove it
}
else {
String cstr = Integer.toHexString(c).toUpperCase();
while(cstr.length()<4){
cstr="0"+cstr;
}
b.append("&#x");
b.append(cstr);
b.append(";");
}
}
return b.toString();
}
因此,这些字符也将转换为相应的Unicode实体。
这会将我所有的PCDATA转换为unicode友好的ASCII字符串。自从使用此技术以来,我再也没有编码问题。我从未输出过未通过此方法传递的XML PCDATA:这并不是在掩盖事实。它只是通过尽可能通用的方式来解决问题。Simpleest解决方案可能会更改您的代码,如下所示:
XMLDocument doc = new XMLDocument(1.0,false,Charset.defaultCharset().toString());
我猜他们只是在使用默认编码向流中写入字符。因此,将默认编码传递到序言中,您就可以了
我同意其他海报的说法,这可能是你最不担心的。看看for ECS,它似乎已经四年没有更新了(“ECS2”存储库也是如此)
还有一些自我提升:如果你想用一个简单的界面来构建XML文档,那么这个库有一个生成器。它使用标准的JDK序列化机制进行输出。你可以向编写器而不是输出流进行写操作……这样你就可以指定编码。我的同事提出了一个解决方案我认为这是正确的方法,但我知道什么。我们没有使用doc.output(stream)
try {
IOUtils.write(doc.toString(), stream, "UTF-8");
} catch (IOException e) {
throw new RuntimeException(e);
}
试一试{
写入(doc.toString(),流,“UTF-8”);
}捕获(IOE异常){
抛出新的运行时异常(e);
}
老实说,我还没有完全理解这个问题,这就是为什么我首先遇到问题的原因。似乎@Subtenant的解决方案通过并转换了UTF-8无法表示的任何字符,并将其替换为unicode实体。这个解决方案似乎像我原来一样使用UTF-8编码写入流ly想要doc.output to。我不知道确切的区别,只是两者都解决了我的问题。如果有任何进一步的评论来帮助我理解这个问题,我将不胜感激。请提供一个代码示例,说明如何使用org.apache.ecs.xml
包,以及如何准备doc
对象。哦,天哪……那英镑在哪里来自?GUI控制?命令行?内联代码?您的问题/格式很酷,不必担心,也很受欢迎!问题不在提供的信息和代码中。乍一看,一切都很好。问题最有可能出现在OutputStream
参数中。它来自何处?在噢,也可能是feedItems本身已经包含了错误的字符。这些字符来自哪里?请调查/调试它。确保您的调试工具(IDE?)本身正在使用UTF-8!不幸的是,我确实看到了这一点,但我希望有某种解决方法。无论如何,感谢您的软件包建议。Charset.defaultCharset()
返回特定于平台的默认字符集,该字符集可能与XML文件编码不同和/或根本不是Unicode派生,例如CP-1252
(哎哟)或者ISO-8859-x
。你不想这样。你之前需要知道XML文件的实际编码。如果你仔细阅读这个问题,你会发现OP实际上在生成XML文件,而不是消费XML文件。如果你仔细阅读我的回答,你会发现我使用XML文件的理由序言中的defaultEncoding()
似乎是第三方库(雅加达ECS)使用它。这解决了错误的问题。他需要对输出流进行UTF-8编码,这与用字符实体替换非ascii数据非常不同。这些字符实体仍将指向拉丁1代码点,而不是必需的UTF-8代码点。正如Jim所写(和我的同事向我指出的)这只是为了掩盖问题。这成了我的临时解决方案,只是因为我需要一个快速解决方案,但当我有时间的时候,我会回去重写我的代码,因为它完全错了。哈哈,太棒了。我对迄今为止唯一能带来一些东西的答案投了反对票。我爱你们朋友。@Jim:我知道我没有以期望的方式回答这个问题是的。如果有人提出了更好的解决方案,我很乐意升级它并在我自己的代码中使用它。到目前为止,清理PCDATA一直是我的最佳方法,在所有情况下都有效。@UmYeah:当您只有ASCII字符时,您的文本是UTF-8编码的。您只是改变了扩展字符的引用方式。您允许客户有责任格式化这些字符。@Jim:“这些字符实体仍将指向拉丁1代码点,而不是必需的UTF-8代码poi
try {
IOUtils.write(doc.toString(), stream, "UTF-8");
} catch (IOException e) {
throw new RuntimeException(e);
}