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 ; 027// import 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 ; 035// import org.opengion.fukurou.system.Closer; // 8.5.4.2 (2024/01/12) PMD 7.0.0 CloseResource 対応 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 * デフォルトコンストラクターをprivateにして、 058 * オブジェクトの生成をさせないようにする。 059 */ 060 private DomParser() {} 061 062 /** 063 * XMLファイルを読み込み、org.w3c.dom.Documentを返す。 064 * 065 * @og.rev 6.4.2.0 (2016/01/29) ex.printStackTrace() を、ThrowUtil#ogStackTrace(Throwable) に置き換え。 066 * 067 * @param aFile XMLファイル 068 * 069 * @return 構築した Document( nullは読み込み失敗 ) 070 */ 071 public static Document read( final File aFile ) { 072 073 Document document = null; 074 try { 075 //---------------------------------------------------- 076 // step1. DocumentBuilderを構築する 077 //---------------------------------------------------- 078 final DocumentBuilderFactory bfactory = DocumentBuilderFactory.newInstance(); 079 final DocumentBuilder builder = bfactory.newDocumentBuilder(); 080 081 //---------------------------------------------------- 082 // step2. XMLファイルを読み込んで、Documentを構築する 083 //---------------------------------------------------- 084 document = builder.parse( aFile ); 085 // 7.2.9.5 (2020/11/28) PMD:'catch' branch identical to 'ParserConfigurationException' branch 086 } catch( final ParserConfigurationException | SAXException | IOException ex) { 087 System.err.println( ex.getMessage() ); 088 System.err.println( ThrowUtil.ogStackTrace( ex ) ); // 6.4.2.0 (2016/01/29) 089 } 090// } catch( final ParserConfigurationException ex) { 091// System.err.println( ex.getMessage() ); 092// System.err.println( ThrowUtil.ogStackTrace( ex ) ); // 6.4.2.0 (2016/01/29) 093// } catch( final SAXException ex) { 094// // 文法エラーが発生した場合 095// System.err.println( ex.getMessage() ); 096// System.err.println( ThrowUtil.ogStackTrace( ex ) ); // 6.4.2.0 (2016/01/29) 097// } catch( final IOException ex) { 098// // ファイルが読み込めなかった場合 099// System.err.println( ex.getMessage() ); 100// System.err.println( ThrowUtil.ogStackTrace( ex ) ); // 6.4.2.0 (2016/01/29) 101// } 102 103 // 完了 104 return document; 105 } 106 107 /** 108 * Documentを指定ファイルに保存する。 109 * 110 * @param aFile 保存先ファイル 111 * @param aDocument Documentインスタンス 112 * 113 * @og.rev 5.1.9.0 (2010/08/01) Closeされないバグを修正 114 * @og.rev 5.6.6.0 (2013/07/05) 若干のインデックス(らしきもの)を入れます 115 * @og.rev 6.3.8.0 (2015/09/11) FileUtil#getPrintWriter( File,String ) を使用。 116 * @og.rev 6.4.0.2 (2015/12/11) Transformer のエラーを、より詳細に出力します。 117 * @og.rev 6.4.2.0 (2016/01/29) ex.printStackTrace() を、ThrowUtil#ogStackTrace(Throwable) に置き換え。 118 * @og.rev 8.5.4.2 (2024/01/12) PMD 7.0.0 CloseResource 対応 119 */ 120 public static void write( final File aFile, final Document aDocument ){ 121 final HybsErrorListener errListener = new HybsErrorListener(); 122// Writer out = null; 123// try { 124 // 8.5.4.2 (2024/01/12) PMD 7.0.0 CloseResource 対応 125 try ( Writer out = FileUtil.getPrintWriter( aFile,"UTF-8" ) ) { // 6.3.8.0 (2015/09/11) 126 //--------------------------------- 127 // step1. Transformerの準備 128 //--------------------------------- 129 final TransformerFactory tFactory = TransformerFactory.newInstance(); 130 // 6.4.0.2 (2015/12/11) TransformerFactory のエラーを、より詳細に出力します。 131 tFactory.setErrorListener( errListener ); 132 133 final Transformer transformer = tFactory.newTransformer(); 134 // 6.4.0.2 (2015/12/11) Transformer のエラーを、より詳細に出力します。 135 transformer.setErrorListener( errListener ); 136 137 //--------------------------------- 138 // step2. Transformerの動作設定 139 //--------------------------------- 140 transformer.setOutputProperty( OutputKeys.INDENT, "yes" ); 141 transformer.setOutputProperty( OutputKeys.METHOD, "xml" ); // 5.6.6.0 (2013/07/05) 142 143 // 5.6.6.0 (2013/07/05) インデントを入れるには、OutputKeys.INDENT だけではだめ。 144 // Xalan の メインの xalan.jarじゃなくて、serializer.jar に入っている OutputPropertiesFactory が必要。 145 // transformer.setOutputPropert( org.apache.xml.serializer.OutputPropertiesFactory.S_KEY_INDENT_AMOUNT, "2" ); 146 147 // この為だけに、また、java の JAVA_HOME/jre/lib/ext を増やすのは嫌なので、OutputPropertiesFactory.S_KEY_INDENT_AMOUNT 148 // で作成している文字列を直接記述しちゃいます。良い子はマネしないでね。 149 transformer.setOutputProperty( "{http://xml.apache.org/xalan}indent-amount", "2" ); 150 151 transformer.setOutputProperty( OutputKeys.ENCODING, "UTF-8" ); 152 153 //--------------------------------- 154 // step3. Writerの準備 155 //--------------------------------- 156 // 6.3.8.0 (2015/09/11) FileUtil#getPrintWriter( File,String ) を使用。 157// out = FileUtil.getPrintWriter( aFile,"UTF-8" ) ; // 6.3.8.0 (2015/09/11) 158 159 //--------------------------------- 160 // step4. 書き出し 161 //--------------------------------- 162 transformer.transform( new DOMSource( aDocument ), new StreamResult( out ) ); 163 } 164 // 7.2.9.5 (2020/11/28) PMD:'catch' branch identical to 'TransformerConfigurationException' branch 165// catch( final TransformerConfigurationException ex ) { 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 catch( final TransformerException ex ) { 171 // 書き出しエラー発生 172 // System.err.println( ex.getMessageAndLocation() ); // 6.4.0.2 (2015/12/11) 行番号がうまく取り出せない。 173 System.err.println( errListener.toString() ); // 6.4.0.2 (2015/12/11) エラー内容が重複するかも。 174 System.err.println( ThrowUtil.ogStackTrace( ex ) ); // 6.4.2.0 (2016/01/29) 175 } 176 // 8.5.4.2 (2024/01/12) try-with-resources にしたため、暗黙的な IOException が発生する。 177 catch( final IOException ex ) { 178 // ファイルがclose できなかった 179 System.err.println( ex.getMessage() ); 180 } 181 // 5.1.9.0 (2010/08/01) Closeされないバグを修正 182// finally { 183// Closer.ioClose( out ); 184// } 185 } 186}