Некоторые символы Unicode возвращаются в виде HTML-кода после анализа - PullRequest
0 голосов
/ 13 февраля 2019

Я пытаюсь проанализировать и отредактировать файл XML, который закодирован в UTF-8, однако некоторые символы возвращаются как то, что выглядит как их цифровые коды HTML, а не как сами символы.

Чтобы устранить эту проблему, я настроил синтаксический анализатор DOM для создания копии XML без каких-либо изменений.Я специально работаю с японскими иероглифами / кандзи, однако некоторые символы анализируются и возвращаются в виде HTML-кодов.Я попытался указать кодировку UTF-8 для входного потока, преобразователя, а также выходного потока, но результаты совпадают.Я взял этот конкретный фрагмент кода из https://www.journaldev.com/901/modify-xml-file-in-java-dom-parser.

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>

1 Ответ

0 голосов
/ 14 февраля 2019

Кажется, что основная проблема заключается в том, что Transformer.transform() будет поддерживать только «чистое» преобразование символов в базовой многоязычной плоскости (BMP), хотя в этой истории может быть что-то большее, чем это.Я клонировал код из вашей ссылки и создал входной XML-файл на основе вашего примера, содержащий несколько символов CJK:

<?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) три символа CJK, которые были в BMPбыли преобразованы правильно, но все они в дополнительной идеографической плоскости (SIP) были преобразованы в escape-коды 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 Сериализация дополнительных символов Unicode в XML-документы с Java , которая не является дубликатом вашей проблемы, но связана с ней.Автор даже поднял отчет об ошибке Xalan для проблемы ToXMLStream не поддерживает дополнительные символы Юникода в 2012 году, которые все еще открыты!

Символ ? (U + 20B9F), который вы упомянулив вашем комментарии это SIP, по-видимому, поэтому он был преобразован в escape-код, тогда как очень похожий символ (U + 53F1) находится в BMP и преобразован правильно.

Я не знаюНе знаю, почему существует эта проблема, но есть несколько возможных причин:

  • Реализация Xalan Transformer.transform() поддерживает только символы в BMP.
  • Реализация Xalan Transformer.transform() не делаетподдерживает преобразование четырехбайтовых символов Unicode.
  • Xalan не был обновлен для поддержки символов CJK, указанных в более поздних расширениях CJK Unified Ideographs.
  • Для преобразования было принято намеренное решение о разработкеSIP символы таким образом.Это может показаться маловероятным, за исключением того, что:
    • Экранирующие коды HTML всегда правильны
    • SIP-символы правильно преобразуются в комментариях.
...