Я просто натыкался на этот же вопрос, и после того, как слишком долго исследовать его, вот что я пришел к выводу.
процессоров Java XSLT избежать мультибайтных UTF-8 символов в HTML сущности даже если режим вывода является XML ... если многобайтовые символы встречаются в тексте() узле, который не завернутый в CDATA. Если символы завернуты в CDATA (для вывода), то многобайтовый символ будет сохранен.
Моя проблема:
У меня была файл XML, который выглядел так, в комплекте с смайликами.
<events>
<event>
<id>RANDOMID</id>
<blah>
<blahId>FOOONE</blahId>
</blah>
<blah>
<blahId>FOOTWO</blahId>
</blah>
<eventComment>Did some things. Had some Fun. </eventComment>
</event>
</events>
Я начал с таблицей стилей XSL, который выглядел так:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/xhtml1/strict"
>
<xsl:output method = "xml" version="1.0" encoding = "UTF-8" omit-xml-declaration="no" indent="yes" />
<xsl:template match="/">
<events>
<xsl:for-each select="/events/event">
<event>
<xsl:copy-of select="./*[name() != 'blah'"/>
<xsl:for-each select="./blah">
<blahId><xsl:copy-of select="./blahId/text()"/></blahId>
</xsl:for-each>
</event>
</xsl:for-each>
</events>
</xsl:template>
</xsl:stylesheet>
Запуск этого с Java Transformer последовательно производится ��
где мои смайлики должны быть. Последующие попытки проанализировать результирующий документ не удались со следующим сообщением об исключении:
org.xml.sax.SAXParseException; lineNumber: y; columnNumber: x; Character reference "�" is an invalid XML character.
HOGWASH!
Тестирование этого с помощью xsltproc
в командной строке было бесполезным, так как xsltproc
не является глупым, когда дело доходит до многобайтовых символов. Я получил ожидаемый результат.
РЕШЕНИЕ
Имея XSLT обернуть eventComment
в CDATA, указав QName в теге cdata-section-elements
атрибут xsl:output
сохранит байт и работает с xsltproc и Java Transformer.
Магия здесь - это результат cdata-secion-elements
property from the <xsl:output>
tag. https://www.w3.org/TR/xslt#output
Я обновил свой шаблон XSL быть:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/TR/xhtml1/strict"
>
<xsl:output cdata-section-elements="eventComment" method="xml" version="1.0" encoding="UTF-8" omit-xml-declaration="no" indent="yes"/>
<xsl:template match="/">
<events>
<xsl:for-each select="/events/event">
<event>
<xsl:copy-of select="./*[name() != 'blah' and name() != 'eventComment']"/>
<!-- For the cdata-section-elements to resolve that eventComment needs to be preserved as CDATA
(so we don't get java doing stupid things with unicode escapment)
it needs to be explicitly referenced here.
-->
<eventComment><xsl:copy-of select="./eventComment/text()"/></eventComment>
<xsl:for-each select="./blah">
<blahId><xsl:copy-of select="./blahId/text()"/></blahId>
</xsl:for-each>
</event>
</xsl:for-each>
</events>
</xsl:template>
</xsl:stylesheet>
А теперь мой выход из обоих xsltproc
и ява Transformer выглядит следующим образом, и разбирает счастливо с ява DocumentBuilders.
<?xml version="1.0" encoding="UTF-8"?>
<events xmlns="http://www.w3.org/TR/xhtml1/strict">
<event>
<id xmlns="">RANDOMID</id>
<eventComment><![CDATA[Did some things. Had some Fun. ]]></eventComment>
<blahId>FOO</blahId>
<blahId>FOOTOO</blahId>
</event>
</events>
Похожие (но, к сожалению, также без ответа) http://stackoverflow.com/questions/15592025/transformer-setoutputpropertyoutputkeys-encoding-utf-8-is-not-working, это выглядит лучше: HTTP: // stackoverflow.com/questions/443305/producing-valid-xml-with-java-and-utf-8-encoding – Tomalak