使用Java将XML文档从Latin1转换为UTF8

时间:2009-12-21 17:07:31

标签: java xml character-encoding

我正在尝试创建一个XML文档(rss feed)并解决了其中的所有问题,除了一个字符编码问题。问题是我使用的是像<?xml version="1.0" encoding="UTF-8"?>这样的UTF-8编码,除了文档本身没有编码为UTF-8。

我正在使用org.apache.ecs.xml包来创建所有标签。然后我使用doc.output(stream)来编写内容。这种方法似乎不使用UTF-8编写输出,我不知道如何实现这一点。在我做之前,一些符号(英镑是我第一次注意到的)在大多数读者中都没有正确呈现。

- 更新了更多信息 -

我最终使用了一个糟糕的解决方案(如评论中所述)来解决这个问题。正确的答案似乎是不要使用org.apache.ecs.xml库。谢谢大家的帮助。 StackOverflow再次获胜。

5 个答案:

答案 0 :(得分:1)

最简单的解决方法可能是更改您的代码,如下所示:

XMLDocument doc = new XMLDocument(1.0,false,Charset.defaultCharset().toString());

我猜他们只是使用默认编码将字符写入流。所以将默认编码传递给序言,你应该没问题。

我同意其他海报,这可能是你最不担心的事情。查看ECS的source repository,它似乎没有更新四年(同样是“ECS2”存储库)。

还有一些自我推销:如果您希望使用简单的界面构建XML文档,Practical XML库就有一个构建器。它使用标准的JDK序列化机制进行输出。

答案 1 :(得分:1)

你有可能写入Writer而不是OutputStream ......你可以用这种方式指定编码。

答案 2 :(得分:1)

这是我的同事提出的解决方案,我认为这是正确的方法,但我知道什么。而不是使用我们使用的doc.output(stream)

    try {
            IOUtils.write(doc.toString(), stream, "UTF-8");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

说实话,我还没有完全理解这个问题,这就是我首先遇到问题的原因。似乎@ subtenante的解决方案经历并转换了UTF-8无法表示的任何字符,并将其替换为unicode实体。这个解决方案似乎使用UTF-8编码写入流,就像我最初想要doc.output一样。我不知道确切的区别,只是两个都解决了我的问题。任何进一步的评论,以帮助我理解这个问题将不胜感激。

答案 3 :(得分:0)

我不熟悉这个软件包,但是从网上的来源我怀疑它可能会被破坏:

http://kickjava.com/src/org/apache/ecs/xml/XMLDocument.java.htm

包含

之类的内容
        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

表明存在问题。

我们使用XOM(http://www.xom.nu),并且在其Serializer上专门有一个setEncoding(),所以我建议更改包...

答案 4 :(得分:0)

这是我写的一个函数,用于将所有非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();
}

将您的输入流读入String content,然后写入输出流xmlEntitify(content)

您的输出保证仅包含ASCII字符,不再存在编码问题。

<强>更新

鉴于这些评论,我会更加大胆:如果你没有对你的数据进行消毒,你就会遇到麻烦。我想你至少已经取代了PCDATA中的<&个字符。如果没有,你肯定应该。我有上述方法的另一个版本,而不是第一个if,它有:

if (c<128 && c!='&' && c!='<' && c!='>' &&  c!='"'){
    b.append(c);
}

这样这些字符也会转换为相应的Unicode实体。 这会将我的所有PCDATA转换为unicode友好的仅ASCII字符串。因为我正在使用这种技术,所以我没有更多的编码问题。我没有输出没有通过这种方法传递的XML PCDATA:这不是将大象扫到地毯下面。它只是通过尽可能通用来摆脱这个问题。