続・JavaでXMLをフォーマットする
前回のエントリ(id:toolkit:20060719)での、id:suchiさんのコメントから、
LSSerializerのDOMConfigrationで ”format-pretty-print” をtrue
という方法を教わったので、早速検証してみます。
結果としては・・・ちょっと微妙な感じになったのでメモしておきます。*1
LSSerializerまでの長い道のり(笑)
LSSerializerはJ2SE 5.0でDOM Level3をサポートする事によって追加されたクラスのようです。
まず、LSSerializerはインターフェースです。なので、どうにかして実装を取ってこなければなりません。
DocumentBuilderFactoryみたいに、Factoryクラスがあるのかな?と思ったら、どうも見当たりません。
しょうがないので、Webをあさって、JavaDoc見て調べてみた結果、
- LSSerializerはDOMImplementationLS#createLSSerializer()で得られる。
- DOMImplementationLSはDocument#getFeature()で得られたオブジェクトをキャストする事によって得られる。
という結論になりました。
Document doc;
※docを作る
DOMImplementation domImpl = doc.getImplementation();
DOMImplementationLS domImplLS = (DOMImplementationLS) domImpl.getFeature("LS", "3.0");
LSSerializer lsSer = domImplLS.createLSSerializer();
ココまでくれば、
lsSer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
とすれば良い・・と思います。
コードにしてみました。
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 org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.w3c.dom.ls.DOMImplementationLS; import org.w3c.dom.ls.LSOutput; import org.w3c.dom.ls.LSSerializer; public class LSSerializerTest01 { 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(); // DOMImplementationLSを取得する DOMImplementation domImpl = doc.getImplementation(); DOMImplementationLS domImplLS = (DOMImplementationLS) domImpl.getFeature("LS", "3.0"); LSOutput lsOutput = domImplLS.createLSOutput(); LSSerializer lsSer = domImplLS.createLSSerializer(); OutputStream out = new FileOutputStream(outXml); lsOutput.setByteStream(out); // LSSerializerのDOMConfigurationにパラメータをセットする lsSer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE); lsSer.write(doc, lsOutput); out.close(); } }
で、実行してみると・・ありゃ、Exception発生。
Exception in thread "main" org.w3c.dom.DOMException: FEATURE_NOT_SUPPORTED: The parameter format-pretty-print is recognized but the requested value cannot be set.
at com.sun.org.apache.xml.internal.serialize.DOMSerializerImpl.setParameter(DOMSerializerImpl.java:267)
なんと!そのパラメータ(format-pretty-print)は認識できるけど、セットできませんと怒られてしまいました(笑)
うーん、今ひとつ釈然としない。メインのソースが悪いのかな・・それともOSXだから??
もう、よくわかんないので、Xercesの最新版をゲットして、パスを通して実行してみると・・・うまく行くではないですか(笑)。*2
Documentオブジェクトの実装は
org.apache.xerces.dom.CoreDOMImplementationImpl
です。
JDKの場合は
com.sun.org.apache.xerces.internal.dom.CoreDOMImplementationImpl
でした。
ってことは、JDKに入っているDOMの実装が古い(?)のかも。
ちなみにJAXPのパッチがあがっていました。
2006/07/13のコメントで、
this will be fixed in Mustang b92.
とあるから、JDK6でサポートされるのかな??
Xercesでもサポートされたのは最近みたい。(2.8からか?)
Implemented the DOM Level 3 Load and Save format-pretty-print parameter.
*1:検証するにあたって、http://jx-study.net/D3pF/D3p.htmlを参考にさせてもらいました。