変更ルールを吸収する仕組み
Wagbyによるインポート処理では、1件の処理毎に、XSLTと呼ばれる変換処理を通ります。
この変換ファイルは directory 要素の importxslfilename 属性で指定されています。標準では次の処理に対応しています。
- 必須項目に値がセットされていない場合に、代わりの値を設定する。
ただし、次のような変更については手動で対応する必要があります。
- 項目の型が変更された場合
- 項目名(英語)が変更された場合
- 主キーや一意項目を追加した場合
通常、このような変更が発生したデータの移行は手間がかかります。しかし Wagby ではインポートに対する個別のルールを XSLT という形で指定できるため、多くの処理を(ルールを追加記述することによって)自動化することができます。すべてのデータを変更しようとする前に、XSLTによるルール記述ができないかどうかを検討してください。
XSLTの書式についての説明は本ガイドの範囲を超えるので割愛します。ここでは、具体的な例を用いて説明します。
注意
このページで紹介する XSLT を用いず、他の開発言語を用いて直接、XML データを変更することもできます。
項目の型が変更された場合
項目の型を「文字列」から「数値」に変更した場合などです。
このとき、項目の値に数値でない文字列があると読み込みエラーとなりますので、このようなデータを無視する、または変換するための処理をXSLT内に記述します。
例:項目 age を文字列から数値型に変更したため、数値以外のデータを無視するように設定する
オリジナルの内容:
<xsl:template match="age">
<age>
<xsl:value-of select="."/>
</age>
</xsl:template>
修正後の内容:
<xsl:template match="age">
<age>
<xsl:if test="number(.) >= 0">
<xsl:value-of select="."/>
</xsl:if>
</age>
</xsl:template>
例:項目 job を文字列からモデル参照に変更したため、元の文字列をコード値に変換する。
オリジナルの内容:
<xsl:template match="job">
<job>
<xsl:value-of select="."/>
</job>
</xsl:template>
修正後の内容:
<xsl:template match="job">
<job>
<xsl:choose>
<xsl:when test="text() = '学生'">
<xsl:text>1</xsl:text>
</xsl:when>
<xsl:when test="text() = '会社員'">
<xsl:text>2</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>-1</xsl:text>
</xsl:otherwise>
</xsl:choose>
</job>
</xsl:template>
例:項目 publishdate の表記内容について「yyyy/MM/dd」を「yyyy-MM-dd」に変換したい。
オリジナルの内容:
<xsl:template match="publishdate">
<publishdate>
<xsl:value-of select="."/>
</publishdate>
</xsl:template>
修正後の内容:
<xsl:template match="publishdate">
<publishdate>
<xsl:choose>
<xsl:when test='contains(text(),"/")'>
<xsl:value-of
select='substring-before(text(),"/")'/>
-<xsl:value-of
select='substring-before(substring-after(
text(),"/"),"/")'/>
-<xsl:value-of select='substring-after(
substring-after(text(),"/"),"/")'/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select='text()'/>
</xsl:otherwise>
</xsl:choose>
</publishdate>
</xsl:element>
項目名(英語)が変更された場合
項目名(英語)が「name」から「customername」に変更された場合など。自動生成された変換用 XSL では、このような意味的な変換は解釈できないため、手動で(変換用 XSL ファイルを)修正し、正しい項目にマッピングします。
例:項目名を「name」から「customername」に変更する。
オリジナルの内容:
<xsl:template match="name">
<name>
<xsl:value-of select="."/>
</name>
</xsl:template>
修正後の内容:
<xsl:template match="name">
<customername>
<xsl:value-of select="."/>
</customername>
</xsl:template>
主キーや一意項目を追加した場合
追加した主キーや一意項目の値が重複しないように配慮する必要があります。
ただしこのケースでは XSL による変換ではなく、対象データを直接、変更する方がよいかも知れません。
項目1,項目2,...を繰り返し項目に統合する
最初の設計を「担当者1」「担当者2」と定義していたが、これを「担当者」(繰り返し項目)に統合する場合です。
元のモデルでエクスポートしたときの XML ファイルが次のようになっていたとします。
<customer>
<id>1000</id>
<name1>山田</name1>
<name2>佐藤</name2>
</customer>
これを、次のような XML に変換した上で、新モデル側にインポートさせます。
<customer>
<id>1000</id>
<name>山田</name>
<name>佐藤</name>
</customer>
変更した XSLT ファイルは次のようになります。
...(中略)...
<xsl:template match="/*">
<customer>
<xsl:choose>
<xsl:when test="id">
<xsl:apply-templates select="id[1]"/>
</xsl:when>
<xsl:otherwise>
<id>-1</id>
</xsl:otherwise>
</xsl:choose>
<xsl:apply-templates select="name"/>
<xsl:apply-templates select="name1"/><!-- 追加 -->
<xsl:apply-templates select="name2"/><!-- 追加 -->
</customer>
</xsl:template>
<xsl:template match="id">
<id>
<xsl:value-of select="."/>
</id>
</xsl:template>
<xsl:template match="name">
<name>
<xsl:value-of select="."/>
</name>
</xsl:template>
<xsl:template match="name1"><!-- 追加 -->
<name>
<xsl:value-of select="."/>
</name>
</xsl:template>
<xsl:template match="name2"><!-- 追加 -->
<name>
<xsl:value-of select="."/>
</name>
</xsl:template>
項目1,項目2,...を繰り返しコンテナに統合する
最初の設計を「担当者1」「担当者2」と定義していたが、これを「担当者」(繰り返しコンテナ内の項目)に統合する場合です。
元のモデルの定義は次のようになっています。
項目名(日本語) |
項目名(英語) |
項目の型 |
主キー |
繰り返し |
ID |
address_id |
整数 |
○ |
|
担当者1 |
con_member_id |
文字列 |
|
|
担当者2 |
con_member_id2 |
文字列 |
|
|
このモデル定義でエクスポートしたときの XML ファイルが次のようになっていたとします。
<address>
<address_id>1000</address_id>
<con_member_id>田中</con_member_id>
<con_member_id2>鈴木</con_member_id2>
</address>
これを次のようなモデル定義に変換します。
項目名(日本語) |
項目名(英語) |
項目の型 |
主キー |
繰り返し |
ID |
address_id |
整数 |
○ |
|
レポート |
report |
(繰り返し項目のコンテナ) |
|
○ |
レポートID |
report/id1 |
(繰り返し項目コンテナ用のID) |
|
|
担当者 |
report/syain |
文字列 |
|
|
メモ |
report/memo |
文字列 |
|
|
日付 |
report/date1 |
日付 |
|
|
具体的には、次に示す XML に変換した上で、新モデル側にインポートさせます。
<address>
<address_id>1000</address_id>
<report>
<reportjshid>0</reportjshid>
<id1>1</id1>
<syain>田中</syain>
</report>
<report>
<reportjshid>1</reportjshid>
<id1>2</id1>
<syain>鈴木</syain>
</report>
</address>
「reportjshid」という項目は、Wagby が内部で利用します。Wagby 定義ファイルには用意されていませんが、インポート時には必要となります。
変更した XSLT ファイルは次のようになります。
...(中略)...
<xsl:template match="/*">
<address>
<xsl:choose>
<xsl:when test="address_id">
<xsl:apply-templates select="address_id[1]"/>
</xsl:when>
<xsl:otherwise>
<address_id>-1</address_id>
</xsl:otherwise>
</xsl:choose>
<xsl:apply-templates
select="report | con_member_id | con_member_id2"/>
</address>
</xsl:template>
<xsl:template match="address_id">
<address_id>
<xsl:value-of select="."/>
</address_id>
</xsl:template>
<xsl:template match="report">
<report>
<xsl:choose>
<xsl:when test="/*/address_id">
<xsl:apply-templates select="/*/address_id[1]"/>
</xsl:when>
<xsl:otherwise>
<address_id>-1</address_id>
</xsl:otherwise>
</xsl:choose>
<reportjshid>
<xsl:value-of select="position()-1"/>
</reportjshid>
<xsl:apply-templates select="id[1]"/>
<xsl:apply-templates select="syain[1]"/>
<xsl:apply-templates select="memo[1]"/>
<xsl:apply-templates select="date1[1]"/>
</report>
</xsl:template>
<xsl:template match="report/id">
<id>
<xsl:value-of select="."/>
</id>
</xsl:template>
<xsl:template match="report/syain">
<syain>
<xsl:value-of select="."/>
</syain>
</xsl:template>
<xsl:template match="report/memo">
<memo>
<xsl:value-of select="."/>
</memo>
</xsl:template>
<xsl:template match="report/date1">
<date1>
<xsl:value-of select="."/>
</date1>
</xsl:template>
<xsl:template match="con_member_id | con_member_id2">
<report>
<xsl:choose>
<xsl:when test="/*/address_id">
<xsl:apply-templates select="/*/address_id[1]"/>
</xsl:when>
<xsl:otherwise>
<address_id>-1</address_id>
</xsl:otherwise>
</xsl:choose>
<reportjshid>
<xsl:value-of select="position()-1"/>
</reportjshid>
<id1>
<xsl:value-of select="position()"/>
</id1>
<syain>
<xsl:value-of select="text()"/>
</syain>
</report>
</xsl:template>
クラシックカレンダーからモダンカレンダーへの変換
「クラシックカレンダビューのデータをモダンカレンダビューへ取り込む」で説明している移行ツールを使うと、クラシックカレンダー形式データを、モダンカレンダー形式で読み込めるようなXSLTファイルが用意されます。
ここで、モデル schedule を題材とします。次の項目を例に説明します。
利用項目 |
クラシック |
モダン |
日付 |
sdate |
- |
開始時刻 |
stime |
- |
終了時刻 |
etime |
- |
開始日時 |
- |
begindate (= sdate + stime) |
終了日時 |
- |
enddate (= sdate + etime) |
XSLTファイル
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml"/>
<xsl:template match="/*">
<schedule>
...
<xsl:apply-templates select="sdate[1]"/> <!-- クラシック形式の日付項目 -->
...
</schedule>
</xsl:template>
<xsl:template match="sdate"> <!-- クラシック形式の日付項目 -->
<begindate> <!-- モダン形式の開始日時 -->
<xsl:choose>
<xsl:when test='contains(text(),"T")'>
<xsl:value-of select='substring-before(text(),"T")'/>
<xsl:text>T</xsl:text>
<xsl:apply-templates select="/*/stime[1]"/> <!-- クラシック形式の開始時刻 -->
</xsl:when>
<xsl:otherwise>
<xsl:value-of select='text()'/>
</xsl:otherwise>
</xsl:choose>
</begindate>
<enddate> <!-- モダン形式の終了日時 -->
<xsl:choose>
<xsl:when test='contains(text(),"T")'>
<xsl:value-of select='substring-before(text(),"T")'/>
<xsl:text>T</xsl:text>
<xsl:apply-templates select="/*/etime[1]"/> <!-- クラシック形式の終了時刻 -->
</xsl:when>
<xsl:otherwise>
<xsl:value-of select='text()'/>
</xsl:otherwise>
</xsl:choose>
</enddate>
</xsl:template>
<xsl:template match="stime | etime">
<xsl:choose>
<xsl:when test='contains(text(),"T")'>
<xsl:value-of select='substring-after(text(),"T")'/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select='text()'/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
- クラシック形式の「日付」+「開始時刻」項目から、モダン形式の「開始日時」項目を用意します。
- クラシック形式の「日付」+「終了時刻」項目から、モダン形式の「終了日時」項目を用意します。
- 日付は内部で"yyyy-MM-ddThh:mm:ss+09:00"となっているため、'T' という文字の前後で日付部と時間部を判断しています。