    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 ) とセットすると、以下の４項目が内部的にセットされます。
    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 * &lt;xsl:param name="ADDRESS" select="" /&gt; と宣言しておき、必要な箇所で
    055 * &lt;xsl:value-of select="$ADDRESS"     /&gt; とすれば、取得できます。
    056 *
    057 *      String inXSTL  = "inXSLfile.xsl" ;   // 入力ＸＳＬファイル
    058 *      String outFile = "outXMLfile.xml" ;  // 出力ＸＭＬファイル
    059 *      String inXML   = "inXMLfile.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 の第３引数を廃止
    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         * &lt;xsl:param name="ADDRESS" select="" /&gt; と宣言しておき、必要な箇所で
    280         * &lt;xsl:value-of select="$ADDRESS"     /&gt; とすれば、取得できます。
    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         * &lt;xsl:param name="ADDRESS" select="" /&gt; と宣言しておき、必要な箇所で
    423         * &lt;xsl:value-of select="$ADDRESS"     /&gt; とすれば、取得できます。
    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}