    001/*
    002 * Copyright (c) 2009 The openGion Project.
    003 *
    004 * Licensed under the Apache License, Version 2.0 (the "License");
    005 * you may not use this file except in compliance with the License.
    006 * You may obtain a copy of the License at
    007 *
    008 *     http://www.apache.org/licenses/LICENSE-2.0
    009 *
    010 * Unless required by applicable law or agreed to in writing, software
    011 * distributed under the License is distributed on an "AS IS" BASIS,
    012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    013 * either express or implied. See the License for the specific language
    014 * governing permissions and limitations under the License.
    015 */
    016package org.opengion.fukurou.xml;
    017
    018import java.io.File ;
    019import java.io.Writer ;
    020import java.io.IOException ;
    021
    022import javax.xml.transform.dom.DOMSource ;
    023import javax.xml.transform.stream.StreamResult ;
    024import javax.xml.transform.Transformer ;
    025import javax.xml.transform.TransformerFactory ;
    026import javax.xml.transform.TransformerException ;
    027import javax.xml.transform.TransformerConfigurationException ;
    028import javax.xml.transform.OutputKeys ;
    029
    030import javax.xml.parsers.DocumentBuilder ;
    031import javax.xml.parsers.DocumentBuilderFactory ;
    032import javax.xml.parsers.ParserConfigurationException ;
    033import org.xml.sax.SAXException ;
    034import org.w3c.dom.Document ;
    035import org.opengion.fukurou.system.Closer;
    036import org.opengion.fukurou.util.FileUtil;                                                      // 6.3.8.0 (2015/09/11)
    037import org.opengion.fukurou.system.ThrowUtil;                                                   // 6.4.2.0 (2016/01/29)
    038
    039/**
    040 * XMLファイルを読み取って、Document オブジェクトを取得する、ユーティリティークラスです。
    041 *
    042 * javax.xml.parsers および、org.w3c.dom の簡易処理を行います。
    043 * read で、Document を読み込み、write で、ファイルに書き出します。
    044 * なお、書き出しに関しては、UTF-8 固定で、かつ、Transformer で行いますので、
    045 * 属性の並び順は、保障されません。(つまり、簡易的な書き出し機能です。)
    046 *
    047 * @og.rev 5.1.7.0 (2010/06/01) 新規作成
    048 *
    049 * @version  5.0
    050 * @author   Kazuhiko Hasegawa
    051 * @since    JDK6.0,
    052 */
    053
    054public final class DomParser {
    055
    056        /**
    057         * プライベート コンストラクター
    058         *
    059         * オブジェクトの作成を拒否します。
    060         */
    061        private DomParser() {}
    062
    063        /**
    064         * XMLファイルを読み込み、org.w3c.dom.Documentを返す。
    065         *
    066         * @og.rev 6.4.2.0 (2016/01/29) ex.printStackTrace() を、ThrowUtil#ogStackTrace(Throwable) に置き換え。
    067         *
    068         * @param       aFile   XMLファイル
    069         *
    070         * @return      構築した Document( nullは読み込み失敗 )
    071         */
    072        public static Document read( final File aFile ) {
    073
    074                Document document = null;
    075                try {
    076                        //----------------------------------------------------
    077                        // step1. DocumentBuilderを構築する
    078                        //----------------------------------------------------
    079                        final DocumentBuilderFactory bfactory = DocumentBuilderFactory.newInstance();
    080                        final DocumentBuilder builder = bfactory.newDocumentBuilder();
    081
    082                        //----------------------------------------------------
    083                        // step2. XMLファイルを読み込んで、Documentを構築する
    084                        //----------------------------------------------------
    085                        document = builder.parse( aFile );
    086
    087                } catch( final ParserConfigurationException ex) {
    088                        System.err.println( ex.getMessage() );
    089                        System.err.println( ThrowUtil.ogStackTrace( ex ) );                             // 6.4.2.0 (2016/01/29)
    090                } catch( final SAXException ex) {
    091                        // 文法エラーが発生した場合
    092                        System.err.println( ex.getMessage() );
    093                        System.err.println( ThrowUtil.ogStackTrace( ex ) );                             // 6.4.2.0 (2016/01/29)
    094                } catch( final IOException ex) {
    095                        // ファイルが読み込めなかった場合
    096                        System.err.println( ex.getMessage() );
    097                        System.err.println( ThrowUtil.ogStackTrace( ex ) );                             // 6.4.2.0 (2016/01/29)
    098                }
    099
    100                // 完了
    101                return document;
    102        }
    103
    104        /**
    105         * Documentを指定ファイルに保存する。
    106         *
    107         * @param aFile 保存先ファイル
    108         * @param aDocument Documentインスタンス
    109         *
    110         * @og.rev 5.1.9.0 (2010/08/01) Closeされないバグを修正
    111         * @og.rev 5.6.6.0 (2013/07/05) 若干のインデックス（らしきもの）を入れます
    112         * @og.rev 6.3.8.0 (2015/09/11) FileUtil#getPrintWriter( File,String ) を使用。
    113         * @og.rev 6.4.0.2 (2015/12/11) Transformer のエラーを、より詳細に出力します。
    114         * @og.rev 6.4.2.0 (2016/01/29) ex.printStackTrace() を、ThrowUtil#ogStackTrace(Throwable) に置き換え。
    115         */
    116        public static void write( final File aFile, final Document aDocument ){
    117                final HybsErrorListener errListener = new HybsErrorListener();
    118                Writer out = null;
    119                try {
    120                        //---------------------------------
    121                        // step1. Transformerの準備
    122                        //---------------------------------
    123                        final TransformerFactory tFactory = TransformerFactory.newInstance();
    124                        // 6.4.0.2 (2015/12/11) TransformerFactory のエラーを、より詳細に出力します。
    125                        tFactory.setErrorListener( errListener );
    126
    127                        final Transformer transformer = tFactory.newTransformer();
    128                        // 6.4.0.2 (2015/12/11) Transformer のエラーを、より詳細に出力します。
    129                        transformer.setErrorListener( errListener );
    130
    131                        //---------------------------------
    132                        // step2. Transformerの動作設定
    133                        //---------------------------------
    134                        transformer.setOutputProperty( OutputKeys.INDENT, "yes" );
    135                        transformer.setOutputProperty( OutputKeys.METHOD, "xml" );                      // 5.6.6.0 (2013/07/05)
    136
    137                        // 5.6.6.0 (2013/07/05) インデントを入れるには、OutputKeys.INDENT だけではだめ。
    138                        // Xalan の メインの xalan.jarじゃなくて、serializer.jar に入っている OutputPropertiesFactory が必要。
    139                        // transformer.setOutputPropert( org.apache.xml.serializer.OutputPropertiesFactory.S_KEY_INDENT_AMOUNT, "2" );
    140
    141                        // この為だけに、また、java の JAVA_HOME/jre/lib/ext を増やすのは嫌なので、OutputPropertiesFactory.S_KEY_INDENT_AMOUNT
    142                        // で作成している文字列を直接記述しちゃいます。良い子はマネしないでね。
    143                        transformer.setOutputProperty( "{http://xml.apache.org/xalan}indent-amount", "2" );
    144
    145                        transformer.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );
    146
    147                        //---------------------------------
    148                        // step3. Writerの準備
    149                        //---------------------------------
    150                        // 6.3.8.0 (2015/09/11) FileUtil#getPrintWriter( File,String ) を使用。
    151                        out = FileUtil.getPrintWriter( aFile,"UTF-8" ) ;                // 6.3.8.0 (2015/09/11)
    152
    153                        //---------------------------------
    154                        // step4. 書き出し
    155                        //---------------------------------
    156                        transformer.transform( new DOMSource( aDocument ), new StreamResult( out ) );
    157
    158                }
    159                catch( final TransformerConfigurationException ex ) {
    160        //              System.err.println( ex.getMessageAndLocation() );       // 6.4.0.2 (2015/12/11) 行番号がうまく取り出せない。
    161                        System.err.println( errListener.toString() );           // 6.4.0.2 (2015/12/11) エラー内容が重複するかも。
    162                        System.err.println( ThrowUtil.ogStackTrace( ex ) );                             // 6.4.2.0 (2016/01/29)
    163                }
    164                catch( final TransformerException ex ) {
    165                        // 書き出しエラー発生
    166        //              System.err.println( ex.getMessageAndLocation() );       // 6.4.0.2 (2015/12/11) 行番号がうまく取り出せない。
    167                        System.err.println( errListener.toString() );           // 6.4.0.2 (2015/12/11) エラー内容が重複するかも。
    168                        System.err.println( ThrowUtil.ogStackTrace( ex ) );                             // 6.4.2.0 (2016/01/29)
    169                }
    170                // 5.1.9.0 (2010/08/01) Closeされないバグを修正
    171                finally {
    172                        Closer.ioClose( out );
    173                }
    174        }
    175}