U+1D49C (
2 に答える
回答が得られず、他の人も同じ問題を抱えているようだったので、さらに調べました...
バグの原因を突き止めるために、 にも使用されている のserializer
ソース コードをXalan 2.7.1
使用しましたXerces
。
org.apache.xml.serializer.dom3.LSSerializerImpl
org.apache.xml.serializer.ToXMLStream
拡張する を使用しますorg.apache.xml.serializer.ToStream
。
ToStream.characters(final char chars[], final int start, final int length)
文字を処理し、Unicode 文字を適切にサポートしていません (注: org.apache.xml.serializer.ToTextSream
(これは で使用できますTransformer
) は、characters メソッドでより適切に機能しますが、プレーン テキストのみを処理し、すべてのマークアップを無視します。XML ファイルはテキストであると考えられます。 、しかし、何らかの理由でToXMLStream
拡張されませんToTextStream
)。
org.apache.xalan.transformer.TransformerIdentityImpl
もorg.apache.xml.serializer.ToXMLStream
( によって返されるorg.apache.xml.serializer.SerializerFactory.getSerializer(Properties format)
) を使用しているため、同じバグに悩まされています。
ToStream
はorg.apache.xml.serializer.CharInfo
、文字を に置き換える必要があるかどうかを確認するために使用してString
いるため、 で直接ではなく、そこでバグを修正することもできますToStream
。は、文字エンティティのリストをCharInfo
含むプロパティ ファイル を使用しているため、このファイルを変更することでorg.apache.xml.serializer.XMLEntities.properties
バグを修正することもできます。パッケージ内のものとは異なるプロパティ ファイルを使用する唯一の方法は、クラスパスの前にファイルを追加することですが、これはあまりクリーンではありません...quot
amp
lt
gt
ToXMLStream
org.apache.xml.serializer.XMLEntities.properties
デフォルトの JDK (1.6 および 1.7) では、 を使用する をTransformerFactory
返します。では、ユニコード文字をより適切に処理できるを呼び出す が呼び出されることがありますが、実際には機能しないようです (ユニコード文字では呼び出されない可能性があります)...com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl
com.sun.org.apache.xml.internal.serializer.ToXMLStream
com.sun.org.apache.xml.internal.serializer.ToStream
characters()
processDirty()
accumDefaultEscape()
processDirty
com.sun.org.apache.xml.internal.serialize.DOMSerializerImpl
com.sun.org.apache.xml.internal.serialize.XMLSerializer
Unicode をサポートするを使用しています。奇妙なことに、XMLSerialize
r は から来ていますが、クラスパス上にあるときXerces
まで使用されていません。これは、の代わりに が利用可能なときにを使用しているためです。クラスパス上で、が使用されます。警告:どちらもマニフェストで参照されるため、同じディレクトリにあり、またはクラスパス上にある場合はクラスパスになります! とのみがクラスパス上にある場合、は として使用され、Unicode 文字は適切に処理されます。Xerces
xalan
xsltc
org.apache.xerces.dom.CoreDOMImplementationImpl.createLSSerializer
org.apache.xml.serializer.dom3.LSSerializerImpl
org.apache.xerces.dom.DOMSerializerImpl
serializer.jar
org.apache.xml.serializer.dom3.LSSerializerImpl
xalan.jar
xsltc.jar
serializer.jar
serializer.jar
xalan.jar
xsltc.jar
xercesImpl.jar
xml-apis.jar
org.apache.xerces.dom.DOMSerializerImpl
LSSerializer
結論と回避策: バグは Apache のorg.apache.xml.serializer.ToStream
クラスにあります ( com.sun.org.apache.xml.internal.serializer.ToStream
JDK 内で名前が変更されます)。Unicode 文字を適切に処理するシリアライザーはorg.apache.xml.serialize.DOMSerializerImpl
( com.sun.org.apache.xml.internal.serialize.DOMSerializerImpl
JDK 内で名前が変更されました) です。ただし、Apache は使用可能な場合よりも優先するため、他の場合にはより適切に動作する可能性がありToStream
ますDOMSerializerImpl
(または、単に再編成されているだけかもしれません)。その上、彼らは で非推奨DOMSerializerImpl
にまでなりましたXerces 2.9.0
。したがって、副作用がある可能性がある次の回避策:
Xerces
および Apacheがクラスパス上にある場合は、" " を " "にserializer
置き換えます(doc.getImplementation()).createLSSerializer()
new org.apache.xerces.dom.DOMSerializerImpl()
Apache
serializer
がクラスパス上にある (たとえば が原因でxalan
) が ではない場合、" " を "new "Xerces
に置き換えてみてください(このクラスは将来消える可能性があるため、フォールバックが必要です)。(doc.getImplementation()).createLSSerializer()
com.sun.org.apache.xml.internal.serialize.DOMSerializerImpl()
これら 2 つの回避策は、コンパイル時に警告を生成します。
の回避策はありませんが、XSLT transforms
これは質問の範囲を超えています。別の DOM ドキュメントに変換して、シリアル化に使用できると思いますDOMSerializerImpl
。
一部の人々にとってはより良い解決策になるかもしれないいくつかの他の回避策:
Saxon
と一緒に使うTransformer
UTF-16
エンコーディングで XML ドキュメントを使用する
これが私のために働いた例です。コードは Java 7 で実行される Groovy で記述されています。この例ではすべての Java API を使用しているため、簡単に Java に変換できます。補足 (プレーン 1) Unicode 文字を含む DOM ドキュメントを渡すと、それらの文字が適切にシリアル化された文字列が返されます。たとえば、ドキュメントに Unicode スクリプト L ( http://www.fileformat.info/info/unicode/char/1d4c1/index.htmを参照) がある場合、返される文字列𝓁
では��
(これはXalan Transformer で得られるもの)。
import org.w3c.dom.Document
...
def String writeToStringLS( Document doc ) {
def domImpl = doc.getImplementation()
def implLS = domImpl.getFeature("LS", "3.0")
def lsOutput = implLS.createLSOutput()
lsOutput.encoding = "UTF-8"
def bo = new ByteArrayOutputStream()
def out = new BufferedWriter( new OutputStreamWriter( bo, "UTF-8") )
lsOutput.characterStream = out
def lsWriter = implLS.createLSSerializer()
def result = lsWriter.write(doc, lsOutput)
return bo.toString()
}