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.Reader; 019import java.io.Writer; 020import java.io.File; 021import java.io.IOException; 022import java.io.StringReader; 023 024import javax.xml.transform.TransformerException; 025import javax.xml.transform.TransformerConfigurationException; 026import javax.xml.transform.TransformerFactory; 027import javax.xml.transform.Transformer; 028import javax.xml.transform.stream.StreamSource; 029import javax.xml.transform.stream.StreamResult; 030import javax.xml.transform.ErrorListener; // 6.4.0.2 (2015/12/11) 031 032import org.opengion.fukurou.system.OgRuntimeException ; // 6.4.2.0 (2016/01/29) 033import org.opengion.fukurou.system.Closer ; 034import org.opengion.fukurou.system.DateSet; // 6.4.2.0 (2016/01/29) 035import org.opengion.fukurou.system.LogWriter; 036import org.opengion.fukurou.util.HybsEntry ; 037import org.opengion.fukurou.util.FileUtil ; 038import org.opengion.fukurou.util.StringUtil ; 039import static org.opengion.fukurou.system.HybsConst.CR; // 6.1.0.0 (2014/12/26) refactoring 040import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE; // 6.1.0.0 (2014/12/26) refactoring 041 042/** 043 * XML 入力ファイルに、XSL 入力ファイルを適用して、XSLT変換を行います。 044 * 結果は、XML 出力ファイルにセーブします。 045 * 各ファイルの代わりに、Writer,Reader を設定することも可能です。 046 * 047 * このパーサーでは、内部で実行中の入力ファイル情報を パラメータとして設定できます。 048 * useFileInfo( true ) とセットすると、以下の4項目が内部的にセットされます。 049 * ただし、この設定が可能なのは、XML 入力ファイルに、Reader ではなく、ファイル名を 050 * 渡した場合のみです。ストリームの場合は、各種情報は取れません。 051 * 052 * 入力ファイル(inXMLのフルパス) : FILEPATH (例: G:\webapps\gf\jsp\DOC10\query.jsp) 053 * 入力親フォルダ(inXMLの親フォルダ) : ADDRESS (例: DOC10) 054 * 入力ファイル(inXMLのファイル名) : FILENAME (例: query.jsp) 055 * 入力ファイル(inXMLの更新日付 ) : MODIFIED (例: yyyyMMddHHmmss形式) 056 * 057 * xsl ファイルでは、パラメータ は、xsl:param で宣言し、xsl:value-of で取り出します。 058 * <xsl:param name="ADDRESS" select="" /> と宣言しておき、必要な箇所で 059 * <xsl:value-of select="$ADDRESS" /> とすれば、取得できます。 060 * 061 * String inXSTL = "inXSLfile.xsl" ; // 入力XSLファイル 062 * String outFile = "outXMLfile.xml" ; // 出力XMLファイル 063 * String inXML = "inXMLfile.xml" ; // 入力XMLファイル 064 * 065 * XSLT xslt = new XSLT(); 066 * xslt.setXslFile( inXSTL ); 067 * xslt.setOutFile( outFile,false ); 068 * 069 * xslt.transform( inXML ); 070 * 071 * @version 4.0 072 * @author Kazuhiko Hasegawa 073 * @since JDK5.0, 074 */ 075public class XSLT { 076 /** 初期 ENCODE 名 {@value} */ 077 public static final String ENCODE = "UTF-8" ; 078 079 private Transformer transformer ; 080 081 private String encode = ENCODE; 082 private String xmlFile ; 083 private String xslFile ; 084 private String outFile ; 085 private Reader xslReader ; 086 private Writer outWriter ; 087 private HybsEntry[] paramEntry ; 088 private boolean isFileInfo ; 089 private boolean isErrClose = true; 090 private boolean isErrXmlIn ; // useErrXmlIn ⇒ isErrXmlIn 変更 091 private boolean isInclude = true; // 4.2.3.0 (2008/05/26) 092 private StreamResult result ; 093 094 private String realPath ; // 5.7.6.2 (2014/05/16) 新規追加 095 private String debugMsg ; // 5.6.7.1 (2013/08/09) デバッグ用 096 097 /** 098 * デフォルトコンストラクター 099 * 100 * @og.rev 8.5.3.2 (2023/10/13) JDK21対応。警告: デフォルトのコンストラクタの使用で、コメントが指定されていません 101 */ 102 public XSLT() { super(); } // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。 103 104 /** 105 * 入力XSLファイルを、指定します。 106 * 107 * @param file 入力XSLファイル 108 * @see #setXslFile( Reader ) 109 */ 110 public void setXslFile( final String file ) { 111 xslFile = file; 112 setXslFile( FileUtil.getBufferedReader( new File( xslFile ),encode ) ); 113 } 114 115 /** 116 * 入力XSLリーダーを、指定します。 117 * 118 * @param reader 入力XSLリーダー 119 * @see #setXslFile( String ) 120 */ 121 public void setXslFile( final Reader reader ) { 122 transformer = null; 123 xslReader = reader; 124 } 125 126 /** 127 * 結果XML ファイル名と、そのオープン方法を指定します。 128 * 結果XML ファイルを、追記する(append=true)か新規作成する(append=false)か指定します。 129 * なお、結果XML ファイル(outFile) を指定しない(=null)か、特別な名称 "System.out" 130 * 文字列を渡すと、標準出力に 結果を出力します。 131 * 132 * @param file 出力ファイル名(null または、"System.out" 文字列時は、標準出力) 133 * @param append [true]追記する/false:新規作成する] 134 */ 135 public void setOutFile( final String file,final boolean append ) { 136 outFile = file ; 137 setOutFile( FileUtil.getPrintWriter( new File( outFile ),encode,append ) ); 138 } 139 140 /** 141 * 結果XML データを出力する、Writer を指定します。 142 * ファイル、標準出力、JSPWriter など、必要に応じて Writer を作成してください。 143 * 標準出力(System.out)の場合は、NonClosePrintWriter クラスなどの非close()処理系を、 144 * JSPWriterの場合は、NonFlushPrintWriter クラスなどの非flush()、close()処理系を、 145 * 使用してください。 146 * 147 * @param writer 出力するWriter 148 */ 149 public void setOutFile( final Writer writer ) { 150 Closer.ioClose( outWriter ); 151 outWriter = writer ; 152 result = new StreamResult( outWriter ); 153 } 154 155 /** 156 * 結果XML ライターに、指定のデータを書き出します。 157 * 158 * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 159 * 160 * @param outData 書き出すデータ 161 */ 162 public void setOutData( final String outData ) { 163 if( outData != null && outData.length() > 0 ) { 164 // 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs) 165 if( outWriter == null ) { 166 final String errMsg = "#setOutFile(Writer)を先に実行しておいてください。" + CR 167 + " outData =" + outData + CR; 168 throw new OgRuntimeException( errMsg ); 169 } 170 171 try { 172 outWriter.write( outData ); 173 outWriter.write( CR ); 174 } 175 catch( final IOException ex ) { 176 final String errMsg = "ライターにデータ登録を失敗しました。" + CR 177 + ex.getMessage() ; 178 close(); 179 throw new OgRuntimeException( errMsg,ex ); 180 } 181 } 182 } 183 184 /** 185 * XML ファイルをXSLT変換します。 186 * XML 入力ファイルに、XSL 入力ファイルを適用して、XSLT変換を行います。 187 * 結果は、XML ファイルにセーブします。 188 * 拡張子が『.jsp』で、かつ、isInclude=true の場合、jsp:directive.include 処理を行います。 189 * 190 * @og.rev 4.2.3.0 (2008/05/26) jsp:directive.include 処理の実施可否を引数指定します。 191 * @og.rev 5.2.1.0 (2010/10/01) JspIncludeReader#getString の第3引数を廃止 192 * @og.rev 5.6.7.1 (2013/08/09) デバッグ用に、ファイルリストを取得しておきます。 193 * @og.rev 5.7.6.2 (2014/05/16) #transform( String , boolean ) 廃止。realPath 追加 194 * 195 * @param file 入力XMLファイル 196 */ 197 public void transform( final String file ) { 198 xmlFile = file; // エラーメッセージ表示時に使用する。 199 200 if( xmlFile.endsWith( ".jsp" ) && isInclude ) { 201 // 5.6.7.1 (2013/08/09) デバッグ用に、ファイルリストを取得しておきます。 202 final JspIncludeReader incReader = new JspIncludeReader(); 203 incReader.setRealPath( realPath ); // 5.7.6.2 (2014/05/16) realPath 追加 204 debugMsg = incReader.getIncludeFiles(); 205 206 final String incData = incReader.getString( new File( xmlFile ),encode ); // 5.2.1.0 (2010/10/01) 207 transform( new StringReader( incData ) ); 208 } 209 else { 210 transform( FileUtil.getBufferedReader( new File( xmlFile ),encode ) ); 211 } 212 } 213 214 /** 215 * XML ファイルをXSLT変換します。 216 * XML 入力リーダーに、XSL 入力リーダーを適用して、XSLT変換を行います。 217 * 結果は、XML ライターに書き出します。 218 * この処理の終了後に、入力XML リーダー は、close() されます。 219 * 220 * @og.rev 5.6.5.2 (2013/06/21) エラーメッセージが判りにくいので、追記します。 221 * @og.rev 5.6.7.1 (2013/08/09) デバッグ用に、ファイルリストを出力します。 222 * @og.rev 6.4.0.2 (2015/12/11) Transformer のエラーを、より詳細に出力します。 223 * @og.rev 8.5.4.2 (2024/01/12) エラー時の情報に 入力ファイル(xmlFile)があれば表示する。 224 * 225 * @param xmlReader 入力XML リーダー 226 * @see #transform( String ) 227 */ 228 public void transform( final Reader xmlReader ) { 229 HybsEntry[] entry = null; 230 231 // transformer は使いまわしますが、ErrorListener は、Reader 毎に再作成します。 232 final ErrorListener errListener = new HybsErrorListener(); // 6.4.0.2 (2015/12/11) 233 try { 234 if( transformer == null ) { 235 init( errListener ); // 6.4.0.2 (2015/12/11) 236 } 237 else { 238 transformer.reset(); 239 transformer.setErrorListener( errListener ); // 6.4.0.2 (2015/12/11) 240 } 241 242 // 入力XMLファイルのファイル情報を設定します。 243 if( isFileInfo && xmlFile != null ) { 244 entry = getXmlParameter( xmlFile ); 245 parameterSet( transformer,entry ); 246 } 247 // 8.5.4.2 (2024/01/12) エラー時の情報に使用するので、クリアは、final で行う。 248// xmlFile = null ; 249 250 // 入力XMLリーダーからStreamSourceを作る 251 final StreamSource data = new StreamSource( xmlReader ); 252 transformer.transform( data,result ); 253 } 254 catch( final TransformerException ex ) { 255 // 5.7.3.0 (2014/02/07) エラー情報をもう少し詳細に取得します。 256 // final String errMsg = ex.getMessageAndLocation() ; 257 final String errMsg = errListener.toString(); // 6.4.0.2 (2015/12/11) さらに詳細に出します。 258 259 final StringBuilder errBuf = new StringBuilder( BUFFER_MIDDLE ) 260 .append( "=====================================================" ).append( CR ) 261 .append( "XML-XSLT 変換に失敗しました。" ).append( CR ) 262 // 8.5.4.2 (2024/01/12) エラー時の情報に 入力ファイル(xmlFile)があれば表示する。 263// .append( errMsg ); 264 .append( errMsg ).append( CR ) 265 .append( " [xmlFile = " ).append( xmlFile ).append( ']' ); 266 267 // 6.3.1.0 (2015/06/28) デバッグ用メッセージを出力します。 268 if( debugMsg != null && debugMsg.length() > 0 ) { 269 errBuf.append( CR ).append( debugMsg ); 270 } 271 272 // 5.6.5.2 (2013/06/21) エラーメッセージが判りにくいので、追記します。 273 if( errMsg.indexOf( "プロローグにはコンテンツを指定できません" ) >= 0 ) { 274 errBuf.append( CR ).append( "\t(UTF-8変換時に、BOMが付くとこのエラーが出ます。BOMを外してみてください。)" ); 275 } 276 277 // 5.6.7.1 (2013/08/09) デバッグ用に、ファイルリストを出力します。 278 if( errMsg.indexOf( "で終了する必要があります" ) >= 0 ) { 279 errBuf.append( CR ).append( "\t(不整合は、includeファイルの可能性があります。)" ); 280 } 281 errBuf.append( CR ); 282 283 if( isErrXmlIn ) { setOutData( toXmlRow( entry, ex ) ); } 284 285 if( isErrClose ) { close(); } 286 287 throw new OgRuntimeException( errBuf.toString(),ex ); 288 } 289 finally { 290 Closer.ioClose( xmlReader ); 291 xmlFile = null ; // 8.5.4.2 (2024/01/12) 292 } 293 } 294 295 /** 296 * Transformer オブジェクトに対して、Parameter を設定します。 297 * 298 * 指定されたパラメーターキーは、xsl ファイルでは、xsl:param で宣言し、 299 * xsl:value-of で取り出します。 300 * <xsl:param name="ADDRESS" select="" /> と宣言しておき、必要な箇所で 301 * <xsl:value-of select="$ADDRESS" /> とすれば、取得できます。 302 * 303 * @param entry HybsEntry配列(可変長引数) 304 */ 305 public void setParamEntry( final HybsEntry... entry ) { 306 if( entry != null && entry.length > 0 ) { // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。 307 paramEntry = new HybsEntry[entry.length]; 308 System.arraycopy( entry,0,paramEntry,0,entry.length ); 309 } 310 } 311 312 /** 313 * transform 処理中にエラーが発生した場合に、出力ファイルを閉じるかどうかを指定します。 314 * 315 * 処理途中でエラーが発生した場合に、そこで処理を中断するか、それとも、 316 * 無視して、さらに処理を進めるかを指定することが可能です。 317 * 継続して処理を進めたい場合は、出力ファイルを閉じないため、false を 318 * 設定します。ただし、エラー時には、RuntimeException は throw されます。 319 * 初期値は、true(閉じる)です。 320 * 321 * @param flag エラー時クローズ [true:閉じる/false:閉じない] 322 */ 323 public void errClose( final boolean flag ) { 324 isErrClose = flag ; 325 } 326 327 /** 328 * transform 処理中エラーを、出力ファイルに、XML形式でエラーを追記するかどうかを指定します。 329 * 330 * 処理途中でエラーが発生した場合に、ログだけではなく、結果XMLファイルに、 331 * エラー内容や、エラーファイルなどを埋め込むと、XMLファイルとしてDB登録や、 332 * その他集計等に使えます。 333 * 今は、GE70 スキーマ形式のファイルしか作成できません。 334 * これは、#errClose( boolean ) メソッドと共に使用すると効果的です。 335 * つまり、errClose = false; にして、エラー時でも出力ファイルを閉じずに、 336 * 処理を続ける事で、エラーメッセージもXMLファイルとして蓄積できます。 337 * 初期値は、false(使用しない)です。 338 * 339 * @param flag エラー時XML形式 [false:使用しない/true:使用する] 340 */ 341 public void useErrXmlIn( final boolean flag ) { 342 isErrXmlIn = flag ; 343 } 344 345 /** 346 * jsp:directive.include 発見時に、そのファイルを INCLUDE するかを指定するかどうかを指定します(初期値:true:使用する) 347 * 348 * 引数の処理対象ファイル(transformの引数ファイル)が、『.jsp』の場合、 349 * jsp:directive.include 発見時に、そのファイルを INCLUDE するかを指定するか 350 * どうかを指定します。 351 * インクルードされたファイルとあわせて、正規のXML にならないと、パーサー 352 * エラーが発生します。 353 * JSPソース解析を行うには、INCLUDE ファイルも考慮しないと正確な結果を 354 * 得られませんが、INCLUDE 先のファイルまで合わせる必要があるため、 355 * 場合によっては、INCLUDEファイルを無視しなければならないケースがあります。 356 * 初期値は、true(使用する)です。 357 * 358 * @param flag エラー時XML形式 [false:使用しない/true:使用する] 359 */ 360 public void jspInclude( final boolean flag ) { 361 isInclude = flag ; 362 } 363 364 /** 365 * jspInclude=true 時に、/jsp/common/** 等の include ファイルが存在しない場合の共有取得場所を指定します。 366 * 367 * 引数の処理対象ファイル(transformの引数ファイル)が、『.jsp』で、かつ、jspInclude=true の場合、 368 * そのファイルを INCLUDE するのですが、/jsp/common/** 等の include ファイルは、 369 * エンジン共通として、jspCommon6.x.x.x.jar で提供しています。 370 * 従来は、処理対象jspの相対パスで、../../../gf/jsp/commom/** を取り込んでいましたが、 371 * Tomcat起動フォルダ以外のシステムのJSPチェックなどを行う場合は、gf フォルダが存在しない 372 * ケースがあります。 373 * そこで、確実にgf が存在する、処理をキックしている環境の gf を使用するように変更します。 374 * その環境とは、つまり、エンジン内部変数の REAL_PATH ですが、jsp などが実行していないと取得できません。 375 * 376 * @param path /jsp/common/** 等の include ファイルの共有取得場所 377 */ 378 public void setRealPath( final String path ) { 379 realPath = path ; 380 } 381 382 /** 383 * 入力XSLファイルのストリームを閉じます。 384 * 385 * @og.rev 5.6.7.1 (2013/08/09) includeしたファイルのキャッシュをクリアします。 386 */ 387 public void close() { 388 Closer.ioClose( outWriter ); 389 390 // 5.6.7.1 (2013/08/09) includeしたファイルのキャッシュをクリア 391 JspIncludeReader.cacheClear(); 392 } 393 394 /** 395 * XML ファイルをXSLT変換します。 396 * XML 入力ファイルに、XSL 入力ファイルを適用して、XSLT変換を行います。 397 * 結果は、XML ファイルにセーブします。 398 * なお、結果XML ファイル(outFile) に、特別な名称 "System.out" 文字列を渡すと、 399 * 標準出力に 結果を出力します。 400 * 401 * @og.rev 5.6.7.1 (2013/08/09) includeしたファイルのキャッシュをクリアします。 402 * @og.rev 6.4.0.2 (2015/12/11) Transformer のエラーを、より詳細に出力します。 403 * 404 * @param errListener ErrorListenerオブジェクト 405 */ 406 private void init( final ErrorListener errListener ) { 407 try { 408 // xsl属性からStreamSourceを作る 409 final StreamSource style = new StreamSource( xslReader ); 410 411 // Transformerを作り、XMLを変換する 412 final TransformerFactory tFactory = TransformerFactory.newInstance(); 413 414 // 6.4.0.2 (2015/12/11) Transformer のエラーを、より詳細に出力します。 415 tFactory.setErrorListener( errListener ); 416 417 transformer = tFactory.newTransformer( style ); 418 // 6.4.0.2 (2015/12/11) Transformer のエラーを、より詳細に出力します。 419 transformer.setErrorListener( errListener ); 420 421 parameterSet( transformer,paramEntry ); 422 423 // 5.6.7.1 (2013/08/09) includeしたファイルのキャッシュをクリア 424 JspIncludeReader.cacheClear(); 425 } 426 catch( final TransformerConfigurationException ex ) { 427 final String errMsg = xslFile + "ファイルの XSLT 解析に失敗しました。" + CR 428 // + ex.getMessageAndLocation() // 6.4.0.2 (2015/12/11) 行番号がうまく取り出せない。 429 + errListener.toString(); // 6.4.0.2 (2015/12/11) エラー内容が重複するかも。 430 throw new OgRuntimeException( errMsg,ex ); 431 } 432 finally { 433 Closer.ioClose( xslReader ); 434 xslReader = null; 435 } 436 } 437 438 /** 439 * 実行中の入力ファイル名などの属性情報を パラメータとして設定するかどうかを指定します。 440 * 441 * このパーサーでは、内部で実行中の入力ファイル情報を パラメータとして設定できます。 442 * useFileInfo( true ) とセットすると、以下の4項目が内部的にセットされます。 443 * 444 * 入力ファイル(inXMLのフルパス) : FILEPATH (例: G:\webapps\gf\jsp\DOC10\query.jsp) 445 * 入力親フォルダ(inXMLの親フォルダ) : ADDRESS (例: DOC10) 446 * 入力ファイル(inXMLのファイル名) : FILENAME (例: query.jsp) 447 * 入力ファイル(inXMLの更新日付 ) : MODIFIED (例: yyyyMMddHHmmss形式) 448 * 449 * @og.rev 4.0.0.0 (2007/09/25) ParameterMetaData を使用したパラメータ設定追加。 450 * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。 451 * 452 * xsl ファイルでは、xsl:param で宣言し、xsl:value-of で取り出します。 453 * <xsl:param name="ADDRESS" select="" /> と宣言しておき、必要な箇所で 454 * <xsl:value-of select="$ADDRESS" /> とすれば、取得できます。 455 * 456 * 初期値は、false(セットしない) です。 457 * 458 * @param flag セットする:true/セットしない:false 459 */ 460 public void useFileInfo( final boolean flag ) { 461 isFileInfo = flag; 462 } 463 464 /** 465 * ファイル名指定で XML,XSL,OUTファイルを指定する場合のエンコードを指定します。 466 * 467 * 初期値は、UTF-8 です。 468 * 469 * @param encode エンコード 470 */ 471 public void useEncode( final String encode ) { 472 this.encode = encode; 473 } 474 475 /** 476 * 実行中の入力ファイル名などの属性情報を パラメータとして取得します。 477 * 478 * 入力ファイル(inXMLのフルパス) : FILEPATH (例: G:\webapps\gf\jsp\DOC10\query.jsp) 479 * 入力ファイル(inXMLのファイル名) : FILENAME (例: query.jsp) 480 * 入力親フォルダ(inXMLの親フォルダ) : ADDRESS (例: DOC10) 481 * 入力ファイル(inXMLの更新日付 ) : MODIFIED (例: yyyyMMddHHmmss形式) 482 * 483 * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。 484 * 485 * @param xmlIn XML入力ファイル 486 * 487 * @return HybsEntry配列 488 */ 489 private HybsEntry[] getXmlParameter( final String xmlIn ) { 490 final HybsEntry[] entry = new HybsEntry[4] ; // 8.5.4.2 (2024/01/12) PMD 7.0.0 LocalVariableCouldBeFinal 491 492 entry[0] = new HybsEntry( "FILEPATH" , xmlIn) ; 493 494 final File xmlFile = new File( xmlIn ); 495 entry[1] = new HybsEntry( "FILENAME" , xmlFile.getName()) ; 496 497 final File parentFile = xmlFile.getParentFile() ; 498 // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..; 499 entry[2] = parentFile == null 500 ? new HybsEntry( "ADDRESS" , "" ) 501 : new HybsEntry( "ADDRESS" , parentFile.getName()) ; 502 503 final String lastDate = DateSet.getDate( xmlFile.lastModified() , "yyyyMMddHHmmss" ) ; // 5.5.7.2 (2012/10/09) HybsDateUtil を利用 504 entry[3] = new HybsEntry( "MODIFIED" , lastDate ) ; 505 506 return entry ; 507 } 508 509 /** 510 * Transformer オブジェクト に、パラメータを設定します。 511 * 512 * 指定されたパラメーターキーは、xsl ファイルでは、xsl:param で宣言し、 513 * xsl:value-of で取り出します。 514 * <xsl:param name="ADDRESS" select="" /> と宣言しておき、必要な箇所で 515 * <xsl:value-of select="$ADDRESS" /> とすれば、取得できます。 516 * 517 * @param former Transformerオブジェクト 518 * @param entry パラメータ配列(可変長引数) 519 */ 520 private void parameterSet( final Transformer former,final HybsEntry... entry ) { 521 if( entry != null && entry.length > 0 ) { // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。 522 final int size = entry.length; 523 for( int i=0; i<size; i++ ) { 524 final String key = entry[i].getKey() ; 525 final String val = entry[i].getValue(); 526 former.setParameter( key , val ); 527 } 528 } 529 } 530 531 /** 532 * このオブジェクトの内部文字列表現を返します。 533 * 534 * 接続URL + "," + 接続ユーザー + " (" + 作成日付 + ")" です。 535 * 536 * @return 内部文字列表現 537 * @og.rtnNotNull 538 */ 539 @Override 540 public String toString() { 541 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ) 542 .append( "XSL File:" ).append( xslFile ).append( CR ) 543 .append( "XML File:" ).append( xmlFile ).append( CR ) 544 .append( "OUT File:" ).append( outFile ).append( CR ); 545 546 return buf.toString() ; 547 } 548 549 /** 550 * エラー情報の内部XML文字列表現を返します。 551 * 552 * エラー時の情報も、XML化して保存する為の簡易処理。 553 * ここでは、XMLスキーマは、固定で、GF70 の形式になります。 554 * 555 * @og.rev 4.2.3.0 (2008/05/26) エラー発生時のXMLファイルを追加します。 556 * @og.rev 5.2.1.0 (2010/10/01) XML形式を変更します。(TEXT⇒TEXT_DATA) 557 * 558 * @param entry HybsEntry配列 559 * @param ex エラー情報 560 * 561 * @return XMLの部分文字列 562 * @og.rtnNotNull 563 */ 564 private String toXmlRow( final HybsEntry[] entry,final TransformerException ex ) { 565 final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE ); 566 567 // 6.0.2.5 (2014/10/31) char を append する。 568 buf.append( "<ROW>" ).append( CR ); 569 if( paramEntry != null ) { 570 // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach 571// for( int i=0; i<paramEntry.length; i++ ) { 572// final String key = paramEntry[i].getKey() ; 573// final String val = paramEntry[i].getValue(); 574 for( final HybsEntry prmEntry : paramEntry ) { 575 final String key = prmEntry.getKey() ; 576 final String val = prmEntry.getValue(); 577 buf.append( " <" ).append( key ).append( '>' ) 578 .append( val ) 579 .append( "</" ).append( key ).append( '>' ) 580 .append( CR ); 581 } 582 } 583 584 if( entry != null ) { 585 // 8.5.4.2 (2024/01/12) PMD 7.0.0 ForLoopCanBeForeach 586// for( int i=0; i<entry.length; i++ ) { 587// final String key = entry[i].getKey() ; 588// final String val = entry[i].getValue(); 589 for( final HybsEntry hent : entry ) { 590 final String key = hent.getKey() ; 591 final String val = hent.getValue(); 592 buf.append( " <" ).append( key ).append( '>' ) 593 .append( val ) 594 .append( "</" ).append( key ).append( '>' ) 595 .append( CR ); 596 } 597 } 598 599 buf.append( " <TAGNAME />" ).append( CR ) // XML なので、このまま。 600 .append( " <MSGCD>XML_ERROR</MSGCD>" ).append( CR ) 601 .append( " <MSGTXT>XML-XSLT 変換に失敗しました。</MSGTXT>" ).append( CR ); 602 603 String errMsg = StringUtil.htmlFilter( ex.getMessage() ); 604 final int indx = errMsg.lastIndexOf( "Exception:" ); 605 if( indx >= 0 ) { 606 errMsg = errMsg.substring( indx + "Exception:".length() ); 607 } 608 buf.append( " <TEXT_DATA>" ).append( errMsg ).append( CR ) // 5.2.1.0 (2010/10/01) 609 .append( " Location:" ).append( ex.getLocationAsString() ).append( CR ) 610 .append( "</TEXT_DATA>" ).append( CR ) // 5.2.1.0 (2010/10/01) 611 .append( "</ROW>" ).append( CR ); 612 613 return buf.toString() ; 614 615/* 616 <ROW> 617 <SYSTEM_ID> </SYSTEM_ID> 618 <ADDRESS > </ADDRESS> 619 <FILENAME > </FILENAME> 620 <FILEPATH > </FILEPATH> 621 <MODIFIED > </MODIFIED> 622 <TAGNAME > </TAGNAME> 623 <MSGCD > </MSGCD> 624 <MSGTXT > </MSGTXT> 625 <TEXT_DATA> </TEXT_DATA> 626 </ROW> 627*/ 628 } 629 630 /** 631 * テスト用のメインメソッド。 632 * 633 * java org.opengion.fukurou.xml.XSLT in_xml in_xsl out_xml 634 * 635 * @param args コマンド引数配列 636 * @throws IOException 入出力エラーが発生した場合 637 */ 638 public static void main( final String[] args ) throws IOException { 639 if( args.length != 3 ) { 640 LogWriter.log( "Usage: java org.opengion.fukurou.xml.XSLT in_xml in_xsl out_xml" ); 641 LogWriter.log( " XML 入力ファイルに、XSL 入力ファイルを適用して、" ); 642 LogWriter.log( " XSLT変換を行います。" ); 643 LogWriter.log( " 結果は、XML ファイルにセーブします。" ); 644 LogWriter.log( " out_xml に System.out を指定すると標準出力に出力します。" ); 645 return ; 646 } 647 648 final XSLT xslt = new XSLT(); 649 xslt.setXslFile( args[1] ); 650 xslt.setOutFile( args[2],false ); 651 xslt.transform( args[0] ); 652 xslt.close(); 653 } 654}