続・続・JavaでXMLをフォーマットする
またも、別の方法があるというコメントいただきました。(id:toolkit:20060719)
transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, ”yes”);
transformer.setOutputProperty(javax.xml.transform.OutputKeys.METHOD, ”xml”);
transformer.setOutputPropert(org.apache.xml.serializer.OutputPropertiesFactory.S_KEY_INDENT_AMOUNT, ”2”);
なので、記事を書いた責任上(?)検証してみます。
実は、最初にこれと似たような事を試しました。
でも、うまく行かなかったんですねぇ。
OutputKeys.INDENT , "yes"
のみ指定していて、それでうまく行かなくてスタイルシート当てようかと思ったんです。
いただいたコメントでの、一番最後の指定がキモですねー。
org.apache.xml.serializer.OutputPropertiesFactory.S_KEY_INDENT_AMOUNT, ”2”
うーん、これは気がつかなかった。
Xalanが必要だった
この、org.apache.xml.serializer.OutputPropertiesFactoryですが、てっきりXercesに入っているのかと思いきや、Xalanに入っているものでした。
しかも、メインのxalan.jarじゃなくて、最近切り離されたらしい(?)serializer.jarに入っています。
使用したコードたち
in.xml
<?xml version="1.0" encoding="UTF-8"?><test><hoge>ほげ</hoge><fuga>ふが</fuga></test>
動作検証用のコード
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Result; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; public class OutputPropertiesFactoryTest01 { public static void main(String[] args) throws Exception { // フォーマットしたいXML File inXml = new File("in.xml"); // フォーマットしたXML File outXml = new File("out.xml"); // フォーマットしたいXMLのDOMオブジェクトを作る DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); InputStream in = new FileInputStream(inXml); Document doc = docBuilder.parse(in); in.close(); // Transformerを用意する。 TransformerFactory transFactory = TransformerFactory.newInstance(); Transformer transformer = transFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); transformer.setOutputProperty( org.apache.xml.serializer.OutputPropertiesFactory.S_KEY_INDENT_AMOUNT,"2"); //書き出し DOMSource source = new DOMSource(doc); OutputStream out = new FileOutputStream(outXml); Result result = new StreamResult(out); transformer.transform(source, result); out.close(); } }
実行してみました。
serializer.jarだけをクラスパスに通して実行します。
out.xml
<?xml version="1.0" encoding="UTF-8"?> <test> <hoge>ほげ</hoge> <fuga>ふが</fuga> </test>
ありゃ?改行はされたけど、インデントされてません。
しょうがないので、xalan.jarもクラスパスに含めて実行します。
out.xml
<?xml version="1.0" encoding="UTF-8"?> <test> <hoge>ほげ</hoge> <fuga>ふが</fuga> </test>
うまく行きました。
っつーことは、結局この方法をとる場合は、XSLTプロセッサ本体もJDK以外のものを使わないと駄目みたい。
これもLSSerializerの時の一緒で、JDKに入っているものが古い(?)のでしょうか。
OutputPropertiesFactoryなるもの
Eclipseさんに聞いてみると、JDKにはcom.sun.org.apache.xml.internal.serializer.OutputPropertiesFactoryがある事が分かりました。
試しに、こっちの方を使って実験してみました。
- JDK
- 改行はされるけどインデントはつかない
- Xalan
- 成功
ちょっと混乱気味(笑)
結局、Xalan本体が必要で、OutputKeys.INDENTに"yes"を指定しただけでは駄目で、OutputPropertiesFactory.S_KEY_INDENT_AMOUNTに数値を指定しなきゃ、という結論でしょうか??
これもJDKの実装がXalanの新しいものになれば、そのうち解決されるって話ですかね??