当前位置: 代码迷 >> java >> 解析后,某些unicode字符将作为其HTML代码返回
  详细解决方案

解析后,某些unicode字符将作为其HTML代码返回

热度:12   发布时间:2023-07-27 09:21:58.0

我正在尝试解析和编辑以UTF-8编码的XML文件,但是某些字符将以其HTML数字代码的形式返回,而不是字符本身。

为了解决这个问题,我设置了一个DOM解析器,使它基本上无需编辑即可复制XML。 我专门使用日语汉字/中文字符,但是某些字符已被解析并作为其HTML代码返回。 我尝试在输入流,转换器和输出流上将编码指定为UTF-8,但结果是相同的。 我从摘录了此特定代码。

String filePath = "file path";
File xmlFile = new File(filePath);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder;
try {
    dBuilder = dbFactory.newDocumentBuilder();
    Document doc = dBuilder.parse(xmlFile);

    doc.getDocumentElement().normalize();
    TransformerFactory transformerFactory = TransformerFactory.newInstance();
    Transformer transformer = transformerFactory.newTransformer();
    DOMSource source = new DOMSource(doc);
    StreamResult result = new StreamResult(new File("updated.xml"));
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
    transformer.transform(source, result);
    System.out.println("XML file updated successfully");

} catch (SAXException | ParserConfigurationException | IOException | TransformerException e1) 
{
    e1.printStackTrace();
}
}

这是XML解析之前的样子,返回后应该看起来一样:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Entry for Kanji: ? -->
<character>
  <literal>?</literal>
</character>

这是什么返回:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Entry for Kanji: ? -->
<character>
  <literal>&#134047;</literal>
</character>

似乎核心问题是Transformer.transform()仅支持基本多语言平面(BMP)中字符的“干净”转换,尽管故事的内容可能还不止这些。 我从您的链接中克隆了代码,并根据包含几个CJK字符的示例创建了一个输入XML文件:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<character>
    <!-- Basic Multilingual Plane -->
    <!-- CJK Unified Ideographs Extension A -->
    <literal>U+3400 ?</literal>
    <literal>U+4DB5 ?</literal>
    <!-- CJK Unified Ideographs Extension -->
    <literal>U+53F1 叱</literal>
    <!-- Supplementary Ideographic Plane -->
    <!-- CJK Unified Ideographs Extension B -->
    <literal>U+20000 ?</literal>
    <literal>U+20B9F ?</literal>
    <literal>U+2A6D6 ?</literal>
    <!-- CJK Unified Ideographs Extension C ? -->
    <literal>U+2A700 ?</literal>
    <literal>U+2B734 ?</literal>
    <!-- CJK Unified Ideographs Extension D -->
    <literal>U+2B740 ?</literal>
    <literal>U+2B81D ?</literal>
</character>

当我运行该应用程序(使用JDK 11)时,BMP中的三个CJK字符已正确转换,但补充表意文字(SIP)中的所有CJK字符均转换为HTML转义码。 这是创建的XML文件:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<character>
    <!-- Basic Multilingual Plane -->
    <!-- CJK Unified Ideographs Extension A -->
    <literal>U+3400 ?</literal>
    <literal>U+4DB5 ?</literal>
    <!-- CJK Unified Ideographs Extension -->
    <literal>U+53F1 叱</literal>
    <!-- Supplementary Ideographic Plane -->
    <!-- CJK Unified Ideographs Extension B -->
    <literal>U+20000 &#131072;</literal>
    <literal>U+20B9F &#134047;</literal>
    <literal>U+2A6D6 &#173782;</literal>
    <!-- CJK Unified Ideographs Extension C ? -->
    <literal>U+2A700 &#173824;</literal>
    <literal>U+2B734 &#177972;</literal>
    <!-- CJK Unified Ideographs Extension D -->
    <literal>U+2B740 &#177984;</literal>
    <literal>U+2B81D &#178205;</literal>
</character>

当我在调试器中运行代码时,JRE似乎将Xalan用于其Transformer.transform() 有一个非常古老的SO post 它将这不是问题的重复,而是相关的。 海报甚至针对在2012年仍不开放的问题提出了Xalan错误报告!

您在注释中提到的字符? (U + 20B9F)在SIP中,这大概就是为什么将其转换为转义码的原因,而非常相似的字符 (U + 53F1)在BMP中并且正确地进行了转换。

我不知道为什么存在此问题,但是有几种可能的原因:

  • Xalan的Transformer.transform()仅支持BMP中的字符。
  • Xalan的Transformer.transform()实现不支持四字节Unicode字符的转换。
  • Xalan尚未更新为支持最新的CJK统一表意文字扩展中指定的CJK字符。
  • 做出了以这种方式转换SIP字符的蓄意设计决定。 这似乎不太可能,除了:
    • HTML转义码始终正确
    • SIP字符在注释中正确转换。
  相关解决方案