17

XMLDom をストリームに書き込む次のメソッドがあります。

public void writeToOutputStream(Document fDoc, OutputStream out) throws Exception {
    fDoc.setXmlStandalone(true);
    DOMSource docSource = new DOMSource(fDoc);
    Transformer transformer = TransformerFactory.newInstance().newTransformer();
    transformer.setOutputProperty(OutputKeys.METHOD, "xml");
    transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
    transformer.setOutputProperty(OutputKeys.INDENT, "no");
    transformer.transform(docSource, new StreamResult(out));
}

他の XML 機能をテストしていますが、これはファイルへの書き込みに使用する方法にすぎません。私のテスト プログラムは、ファイルが書き出される 33 のテスト ケースを生成します。それらの 28 には、次のヘッダーがあります。

<?xml version="1.0" encoding="UTF-8"?>...

しかし、何らかの理由で、テスト ケースの 1 つで次の結果が生成されるようになりました。

<?xml version="1.0" encoding="ISO-8859-1"?>...

そして、さらに4つが生産されます:

<?xml version="1.0" encoding="Windows-1252"?>...

ご覧のとおり、ENCODING 出力キーを UTF-8 に設定しています。これらのテストは、以前のバージョンの Java で機能していました。しばらく (1 年以上) テストを実行していませんが、今日 "Java(TM) SE ランタイム環境 (ビルド 1.6.0_22-b04)" で実行すると、この奇妙な動作が発生します。

問題の原因となっているドキュメントが、元々これらのエンコーディングを持つファイルから読み取られたことを確認しました。ライブラリの新しいバージョンは、読み込まれたソース ファイルのエンコーディングを保持しようとしているようです。しかし、それは私が望んでいることではありません...出力をUTF-8にしたいのです。

トランスフォーマーが UTF-8 エンコード設定を無視する可能性のある他の要因を知っている人はいますか? 最初に読み取られたファイルのエンコーディングを忘れるために、ドキュメントに設定する必要があるものは他にありますか?

アップデート:

同じプロジェクトを別のマシンでチェックアウトし、そこでビルドしてテストを実行しました。そのマシンでは、すべてのテストに合格しました! すべてのファイルのヘッダーに「UTF-8」が含まれています。そのマシンには「Java(TM) SE Runtime Environment (build 1.6.0_29-b11)」があります。どちらのマシンも Windows 7 を実行しています。正常に動作する新しいマシンでは、jdk1.5.0_11 を使用してビルドを作成しますが、古いマシンではビルドを作成します。マシン jdk1.6.0_26 を使用してビルドを行います。両方のビルドに使用されるライブラリはまったく同じです。ビルド時の JDK 1.6 と 1.5 の非互換性はありますか?

アップデート:

4.5 年経っても Java ライブラリは壊れたままですが、以下の Vyrx の提案により、ようやく適切な解決策が見つかりました!

public void writeToOutputStream(Document fDoc, OutputStream out) throws Exception {
    fDoc.setXmlStandalone(true);
    DOMSource docSource = new DOMSource(fDoc);
    Transformer transformer = TransformerFactory.newInstance().newTransformer();
    transformer.setOutputProperty(OutputKeys.METHOD, "xml");
    transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
    transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    transformer.setOutputProperty(OutputKeys.INDENT, "no");
    out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>".getBytes("UTF-8"));
    transformer.transform(docSource, new StreamResult(out));
}

解決策は、ヘッダーの書き込みを無効にし、XML を出力ストリームにシリアル化する直前に正しいヘッダーを書き込むことです。ラメですが、正しい結果が得られます。4 年以上前に壊れたテストが再び実行されています!

4

8 に答える 8

1

DOMSource コンストラクターに渡された Document オブジェクトをラップすることで、この問題を回避できます。私のラッパーのメソッド getXmlEncoding は常に null を返し、他のすべてのメソッドはラップされた Document オブジェクトに委譲されます。

于 2016-07-06T20:12:46.947 に答える