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 org.opengion.fukurou.util.Closer ;
019import org.opengion.fukurou.util.HybsEntry ;
020import org.opengion.fukurou.util.FileUtil ;
021import org.opengion.fukurou.util.StringUtil ;
022import org.opengion.fukurou.util.LogWriter;
023import org.opengion.fukurou.util.HybsDateUtil ;
024
025import java.io.Reader;
026import java.io.Writer;
027import java.io.File;
028import java.io.IOException;
029import java.io.StringReader;
030
031import javax.xml.transform.TransformerException;
032import javax.xml.transform.TransformerConfigurationException;
033import javax.xml.transform.TransformerFactory;
034import javax.xml.transform.Transformer;
035import javax.xml.transform.stream.StreamSource;
036import javax.xml.transform.stream.StreamResult;
037
038/**
039 * XML 入力ファイルに、XSL 入力ファイルを適用して、 XSLT変換を行います。
040 * 結果は、XML 出力ファイルにセーブします。
041 * 各ファイルの代わりに、Writer,Reader を設定することも可能です。
042 *
043 * このパーサーでは、内部で実行中の入力ファイル情報を パラメータとして設定できます。
044 * useFileInfo( true ) とセットすると、以下の4項目が内部的にセットされます。
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" ;   // 入力XSLファイル
058 *      String outFile = "outXMLfile.xml" ;  // 出力XMLファイル
059 *      String inXML   = "inXMLfile.xml" ;   // 入力XMLファイル
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 */
071public 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 の第3引数を廃止
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 ) とセットすると、以下の4項目が内部的にセットされます。
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}