CB3 - チュートリアル 第3章 - 3.9XMLファイルアクセス - その1

 3.9.1概要

  • このサンプルの目的
     このアプリケーション作成例を通して、以下について知ることができます。
    • サービスでXMLファイルを扱う場合のXMLファイル(ライタ、リーダ)アクセッサの使用方法
    • XMLファイルアクセッサを使用するときのXMLファイル設定ファイルの作成方法

  • サンプルアプリケーションの内容
     XMLファイルへの書込み、読込みを行い読み込み結果を標準出力へ表示するバッチアプリケーションです。  
     サンプルアプリケーションの概要を下図に示します。
     
     
     サービスでXMLファイルにアクセスする場合は、CB3が提供するXMLファイル(ライタ、リーダ)アクセッサを利用します。
     XMLファイルアクセッサは、設定ファイルのXMLファイル(ライタ、リーダ)設定ファイルの内容をもとにファイルへの書込み、読込みを行います。
     
     このサンプルでは以下のファイルについて説明します。  
    • XMLAccess.java
       サービスのプログラムです。上図内の赤枠の部分に相当します。
    • writerConfig.xml
       XMLファイルライタ設定ファイルです。上図内のXMLファイルライタ設定ファイルに相当します。
    • readerConfig.xml
       XMLファイルリーダ設定ファイルです。上図内のXMLファイルリーダ設定ファイルに相当します。
    • applicationContext.xml
       CB3がserviceContext.xmlなどのspringフレームワーク関連の設定ファイルを読み込むための起点となる コンテキストファイルです。
      このファイルは内容が「3.5固定長ファイルアクセス - その1」と同じため省略します。
    • serviceContext.xml
       実行対象のサービスを定義します。
    • 起動用バッチファイル - xmlaccess.bat
       サービスを起動するためのバッチファイルです。
    • testXML.xml
       書込み読込み対象のファイルです。

 3.9.2サービスの作成

  • XMLAccess.java

     01:public class XMLAccess extends CB3Service {
     02:    private static final String FILE_PATH = "testXML.xml";
     03:    @Override
     04:    protected int doService(ServiceParameters serviceparameters,
     05:            RuntimeParameters runtimeparameters) throws ServiceException {
     06:        fileWrite();
     07:        fileRead();
     08:        return 0;
     09:    }
     10:
     11:    /**
     12:     * XMLファイルへの書き込みを行う
     13:     */
     14:    private void fileWrite(){
     15:
     16:        //XML書き出し用アクセッサを取得
     17:        XMLFileWriter writer = (XMLFileWriter)getDataAccessContext().lookup("writerConfig");
     18:        writer.open(FILE_PATH);
     19:
     20:        //書き出す要素を生成する
     21:        XMLElement topElement = new XMLElement("conversation");
     22:        XMLElement greetingElement = new XMLElement("greeting");
     23:        XMLElement jpElement = new XMLElement("thanks");
     24:        XMLElement usElement = new XMLElement("thanks");
     25:
     26:        //属性をセットする
     27:        jpElement.putAttribute(new XMLAttribute("language","japanese"));
     28:        usElement.putAttribute(new XMLAttribute("language","english"));
     29:
     30:        //要素をセットする
     31:        jpElement.setString("ありがとう");
     32:        usElement.setString("thank you.");
     33:
     34:        //書き出す
     35:        writer.startElement(topElement);
     36:        writer.startElement(greetingElement);
     37:
     38:        writer.dataElement(jpElement);
     39:        writer.dataElement(usElement);
     40:
     41:        writer.endElement(greetingElement);
     42:        writer.endElement(topElement);
     43:
     44:        writer.close();
     45:    }
     46:
     47:    /**
     48:     * ファイルの読み込みを行う
     49:     */
     50:    private void fileRead(){
     51:
     52:        // XML読み込み用アクセッサを取得
     53:        XMLFileReader reader = (XMLFileReader) getDataAccessContext().lookup("readerConfig");
     54:        reader.open(FILE_PATH);
     55:
     56:        // conversation要素を検索する
     57:        XMLPath topPath = reader.selectPath("conversation");
     58:
     59:        // conversation要素を取得する
     60:        XMLElement topElement = topPath.next();
     61:        System.out.println("要素名=[" + topElement.getName() + "]");
     62:
     63:        // thanks要素を検索する
     64:        XMLPath thanksPath = topPath.selectChildPath("greeting/thanks");
     65:
     66:        // thanks要素を取得する
     67:        XMLElement thanksElement;
     68:        while ((thanksElement = thanksPath.next()) != null) {
     69:            // 属性を取得する
     70:            XMLAttribute attr = thanksElement.getAttributes().getAttribute("language");
     71:            System.out.println("要素名=[" + thanksElement.getName() + "], 属性名=[" + attr.getName()
     72:                    + "], 属性値=[" + attr.getString() + "], 要素=[" + thanksElement.getString()
     73:                    + "]");
     74:        }
     75:
     76:        reader.close();
     77:    }
     78:}
    

    このサンプルはファイルへの書込み処理(14行目:fileWrite())を行った後、書込んだファイルの読込み(50行目:fileRead())処理を行っています。

    以下のXMLの書込みと読込みを行います。
    <conversation>
      <greeting>
        <thanks language="japanese">ありがとう</thanks>
        <thanks language="english">thank you.</thanks>
      </greeting>
    </conversation>
    

    ■書込み処理
    17行目:
    XMLファイルライタの取得を行います。この処理はDBアクセスのサンプルで紹介したときと同じようにlookup()メソッドで行います。

    18行目:
    open()メソッドでファイルのオープンを行います。引数にはオープンするファイルパスを設定します。

    21行目〜24行目:
    ファイルに出力するXMLの要素を生成します。

    27行目〜28行目:
    XML要素の属性を追加します。複数の属性を追加したい場合にはputAttribute()メソッドを複数回実行します。

    31行目〜32行目:
    XML要素の値を設定します。

    35行目:
    「conversation」要素の開始タグ「<conversation>」を出力します。要素の終了タグ「</conversation>」を出力するには endElement()メソッドを実行します。

    36行目:
    「greeting」要素の開始タグを出力します。「conversation」要素の中に「greeting」要素を含めるため、「conversation」要素の終了タグ 「</conversation>」を出力する前にこの行を実行します。

    38行目〜39行目:
    「thanks」要素の属性と値を出力します。dataElement()メソッドは開始タグを出力するstartElement()メソッドと要素の値を出力するcharacters()メソッド、 終了タグを出力するendElement()メソッドを内部的に順次実行します。

    41行目〜42行目:
    「greeting」要素と「conversation」要素の終了タグを出力します。

    ■読込み処理
    53行目:
    XMLファイルリーダの取得を行います。この処理はDBサクセスのサンプルで紹介したときと同じようにlookup()メソッドで行います。

    54行目:
    open()メソッドでファイルのオープンを行います。引数にはオープンするファイルパスを設定します。

    57行目:
    XMLファイルから「conversation」要素を検索します。selectPath()メソッドの引数にはXQueryの形式を指定します。

    60〜61行目:
    「conversation」要素を取得し、その要素名を出力します。

    64行目:
    「conversation」要素に含まれる「thanks」要素を検索します。子の要素を検索する場合には親の検索で取得したXMLPathの selectChildPath()メソッドを使用して検索します。この例では「conversation」要素の検索で取得したtopPathで検索しています。

    67〜74行目:
    「thanks」要素を取得し、その要素名と属性名、属性値、要素を出力します。

 3.9.3設定ファイルの作成

  • writerConfig.xml
    XMLファイルライタの設定ファイルです。

     01:<?xml version="1.0" encoding="UTF-8"?>
     02:<xml-writer
     03:  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     04:  xsi:noNamespaceSchemaLocation="XMLFileWriterConfig.xsd">
     05:  <format>
     06:  </format>
     07:</xml-writer>
    

    このサンプルでは設定項目をすべて省略しています。
    XMLファイルライタ設定ファイルに設定できるタグとして、filepathタグ、encodeタグ、lineSeparatorタグ、indentSpaceタグがあります。 どちらもxml-writer/formatタグの子要素として定義できます。

    filepathタグ:
    filepathタグには書き込み対象のファイルパスを指定することができます。このサンプルではopen()メソッドにファイルパスを指定しているので 設定ファイルでは省略しています。また、open()メソッドはこの設定を上書きすることができます。
    設定例:<filepath>C:/data/sample.xml</filepath>

    encodeタグ:
    encodeタグにはエンコードの文字コードを指定することができます。指定がない場合はシステムのデフォルトエンコードを使用します。 文字コードはjava.nio.charset.Charsetの名前を指定できます。より詳しい説明についてはCharsetクラスのjavadocを参照してください。
    設定例:<encode>SJIS</encode>

    lineSeparatorタグ:
    lineSeparatorタグには改行コードを指定することができます。指定できる改行コードの有効値は「\r」「\r\n」「\n」の3つです。 指定がない場合はシステムのデフォルト改行コードを使用します。
    設定例:<lineSeparator>\r</lineSeparator>

    indentSpaceタグ:
    indentSpaceタグには子要素を出力する場合の空白文字のインデント数を指定します。指定がない場合はデフォルト値の「2」を使用します。
    設定例:<indentSpace>4</indentSpace>

  • readerConfig.xml
    XMLファイルリーダの設定ファイルです。

     01:<?xml version="1.0" encoding="UTF-8"?>
     02:<xml-reader
     03:  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     04:  xsi:noNamespaceSchemaLocation="XMLFileReaderConfig.xsd">
     05:  <format>
     06:    <filepath>testXML.xml</filepath>
     07:  </format>
     08:</xml-reader>
    

    XMLファイルリーダ設定ファイルにはfilepathタグのみ設定できます。このタグはxml-reader/formatタグの子要素として定義できます。

    filepathタグ:
    filepathタグには読み込み対象のファイルパスを指定することができます。 ここで記述せずにopen()メソッドにファイルパスを指定することもできます。 その場合はopen()メソッドがこの設定を上書きします。
    設定例:<filepath>C:/data/sample.xml</filepath>

  • serviceContext.xml
    このサンプルの実行に必要となるサービスのコンテキストファイルです。

     01:<?xml version="1.0" encoding="UTF-8"?>
     02:    <-- 途中省略 -->
     03:
     04:    <!-- ServiceProvider -->
     05:    <bean id="xmlaccess" class="jp.co.cybec.cb3.container.provider.ServiceProviderImpl">
     06:        <property name="service"><ref bean="sample5"/></property>
     07:    </bean>
     08:    <!-- Service -->
     09:    <bean id="sample5" class="jp.co.cybec.cb3.sample.xml.xmlaccess.XMLAccess">
     10:        <property name="dataAccessContext"><ref bean="accessContext"/></property>
     11:    </bean>
     12:    <!-- DataAccessContext -->
     13:    <bean id="accessContext" class="jp.co.cybec.cb3.accessor.DataAccessContextImpl">
     14:        <constructor-arg index="0"><ref bean="testDataAccessors"/></constructor-arg>
     15:    </bean>
     16:    <util:map id="testDataAccessors">
     17:        <entry key="readerConfig"><ref bean="xmlFileReader"/></entry>
     18:        <entry key="writerConfig"><ref bean="xmlFileWriter"/></entry>
     19:    </util:map>
     20:</beans>
    

    17行目〜18行目:
    XMLファイルアクセッサの設定を行っています。このサンプルでは書込み処理と読込み処理を行っているので XMLファイルリーダとXMLファイルライタの二つの設定を行っています。

 3.9.4サービスの実行

  • xmlaccess.bat
     01:@echo off
     02:
     03:setlocal
     04:
     05:call ./set_classpath_com.bat
     06:
     07:set CLASSPATH=%CB3_HOME%/resources/config/xmlaccess;%CLASSPATH%
     08:
     09:java jp.co.cybec.cb3.container.provider.ServiceProviderImpl -ServiceName xmlaccess
     10:
     11:pause
    

    上記バッチファイルを実行すると下記のように表示されます。

    要素名=[conversation]
    要素名=[thanks], 属性名=[language], 属性値=[japanese], 要素=[ありがとう]
    要素名=[thanks], 属性名=[language], 属性値=[english], 要素=[thank you.]
    続行するには何かキーを押してください . . .
    

    testXML.xml確認すると以下のようにデータが登録されています。