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