私はちょうどこの同じ問題に出くわしました. あまりにも長い間調査した後、これが私が結論付けたことです.
Java XSLT プロセッサは、出力モードが XML の場合でも、マルチバイト UTF-8 文字を HTML エンティティにエスケープします...マルチバイト文字が CDATA でラップされていない text() ノードで発生した場合。文字が (出力用に) 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.
ホグウォッシュ!
マルチバイト文字に関しては愚かではないxsltproc
ため、コマンドラインでこれをテストしても役に立ちませんでした。xsltproc
期待どおりの出力が得られました。
解決策
tag属性で QName を指定して XSLTeventComment
で CDATA をラップすると、バイトが保持され、 xsltprocおよび Java Transformerで動作します。xsl:output
cdata-section-elements
ここでの魔法は、タグcdata-secion-elements
からの出力プロパティです。https://www.w3.org/TR/xslt#output<xsl: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>
そして、Java Transformer と Java Transformer の両方からの出力はxsltproc
次のようになり、Java 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>