こんにちは。CData Software Japanの色川です。
この記事では、ArcESB のコアコネクタの1つであるXSLT コネクタをご紹介します。
ArcESB のXSLT コネクタは、指定したXSL ファイルの定義に従ってXML 構造を自動的に変換できるコネクタです。
現在REST スタイルで提供されているAPI は多いですが、REST スタイルのAPI と一口に言っても、扱いやすいモノからそうでないモノまで様々です。
中には少々扱いにくいレスポンスが返ってくるケースもありますが、そういった扱いにくいデータ構造を相手に連携フローを組んでいくのは開発も維持もなかなか大変です。そういった時は無理にそのまま扱わず、まずは扱いやすいデータ構造に変換してしまうのも1つのアプローチだと思います。XSLT コネクタはそんな時にも活用できます。
この記事のシナリオ
この記事では、こちらのセッションで触れている「奇妙なレスポンス形式」を持つAPI と連携しなければならなくなった時を例にして、XSLT コネクタを活用して連携フローを作成してみます。
(あまり出会いたくない)扱いにくいレスポンス形式については、こちらの記事も併せてご覧ください。
この記事で扱うフロー
ArcESB では連携フローを流れるメッセージの形式としてXML を利用しています。REST コネクタなどで「API をコールしてJSON が返されたら、JSON コネクタでXML に変換して後続のフローに連携していく」のは良くあるパターンです。
この記事では「API から返されたJSON をデータベースへUpsert する」シンプルなシナリオにしています。Upsert するテーブルはそのままマッピングすればOK の分かりやすい構造にしています。
このシンプルなシナリオで、奇妙なレスポンス形式(API から返されるJSON が扱いにくい形式)のとき、XSLT を利用して扱いやすいデータ構造に変えてから連携フローをつないでみます。
扱いやすいレスポンス形式の場合
まずは「奇妙なレスポンス形式」を扱う前に、一般的に期待される扱いやすいレスポンスを対象にしたときのフローです。
customer を返すAPI があるとして、このようなレスポンスだと素直に扱いやすいですよね。
{ "customer": [ { "Id": "1", "Name": "John", "Gender": "M", "Age": 21 }, { "Id": "2", "Name": "Tom", "Gender": "M", "age": 47 }, { "Id": "3", "Name": "Jane", "Gender": "F", "age": 34 } ] }
データ構造をそのまま考えると、以下のような素直なテーブルイメージです。
ArcESB のJSON コネクタを通すと、以下のようなXML に変換されます。
<?xml version="1.0" encoding="utf-8"?> <Items xmlns:json="http://www.arcesb.com/ns/jsonconnector" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <customer json:array="true"> <Id>1</Id> <Name>John</Name> <Gender>M</Gender> <Age json:type="number">21</Age> </customer> <customer json:array="true"> <Id>2</Id> <Name>Tom</Name> <Gender>M</Gender> <age json:type="number">47</age> </customer> <customer json:array="true"> <Id>3</Id> <Name>Jane</Name> <Gender>F</Gender> <age json:type="number">34</age> </customer> </Items>
この形式であれば、その後のフローであるXML Map でのデータベースへのマッピングも素直で分かりやすく簡単です。
フロー自体は、以下のようなシンプルな流れです。
コネクタ | 内容 | |
---|---|---|
1 | JSON | (API レスポンスをイメージした)JSON ファイルの読み込みとXML への変換 |
2 | XML Map | 1.の結果を3.にマッピング |
3 | SQL Server | SQL Server へUpsert |
奇妙なレスポンス形式の場合(キーが値になっている)
まずは、こちらのケースです。
{ "customer": { "1": { "Name": "John", "Gender": "M", "Age": 21 }, "2": { "Name": "Tom", "Gender": "M", "Age": 47 }, "3": { "Name": "Jane", "Gender": "F", "Age": 34 } } }
キーが値になっていて、そのまま変換すると以下のようなイメージになってしまいますよね。
このJSON ファイルは、JSON コネクタを通すと、以下のようなXML に変換されます。
<?xml version="1.0" encoding="utf-8"?> <Items xmlns:json="http://www.arcesb.com/ns/jsonconnector" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <customer> <__1> <Name>John</Name> <Gender>M</Gender> <Age json:type="number">21</Age> </__1> <__2> <Name>Tom</Name> <Gender>M</Gender> <Age json:type="number">47</Age> </__2> <__3> <Name>Jane</Name> <Gender>F</Gender> <Age json:type="number">34</Age> </__3> </customer> </Items>
これでは、Mapping(XML Map)においても繰り返すレコード単位の判断ができませんし、扱いにくいです。
そこで、JSON コネクタでXML に変換されたデータを、以下のようなXSL で扱いやすい形に変換してみます。ここでは、/Items/customer 配下のノードを対象に、ノードの名前を customer Id の値とするように変換しています。
<?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" indent="yes" /> <xsl:template match="/Items/customer/*"> <customer> <Id><xsl:value-of select="translate(name(),'__','')" /></Id> <Name><xsl:value-of select="Name" /></Name> <Gender><xsl:value-of select="Gender" /></Gender> <Age><xsl:value-of select="Age" /></Age> </customer> </xsl:template> <xsl:template match="/*"> <Items> <xsl:apply-templates /> </Items> </xsl:template> </xsl:stylesheet>
JSON コネクタの出力を、XSLT コネクタにつなぎます。
変換ロジックを定義したXSL ファイルをXSLT コネクタに指定します。
これにより、JSON コネクタでXML に変換したデータが、XSLT コネクタを通過すると、以下のようなXML に変換されます。
<?xml version="1.0" encoding="utf-8"?> <Items> <customer> <Id>1</Id> <Name>John</Name> <Gender>M</Gender> <Age>21</Age> </customer> <customer> <Id>2</Id> <Name>Tom</Name> <Gender>M</Gender> <Age>47</Age> </customer> <customer> <Id>3</Id> <Name>Jane</Name> <Gender>F</Gender> <Age>34</Age> </customer> </Items>
こうすれば、後続のフローは、先ほどと同じ「扱いやすいデータ構造」を相手にできますので、後続のMapping(XML Map)も素直で簡単です。
奇妙なレスポンス形式の場合(要素が離れている)
今度はこちらのケースです。
{ "customer": { "Id": { "0": "1", "1": "2", "2": "3" }, "Name": { "0": "John", "1": "Tom", "2": "Jane" }, "Gender": { "0": "M", "1": "M", "2": "F" }, "Age": { "0": 21, "1": 47, "2": 34 } } }
1人のcustomer を表す関連する要素が離れてしまっています。こちらはそのまま変換すると以下のようなイメージになってしまいますよね。
このJSON ファイルは、JSON コネクタを通すと、以下のようなXML に変換されます。
<?xml version="1.0" encoding="utf-8"?> <Items xmlns:json="http://www.arcesb.com/ns/jsonconnector" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <customer> <Id> <__0>1</__0> <__1>2</__1> <__2>3</__2> </Id> <Name> <__0>John</__0> <__1>Tom</__1> <__2>Jane</__2> </Name> <Gender> <__0>M</__0> <__1>M</__1> <__2>F</__2> </Gender> <Age> <__0 json:type="number">21</__0> <__1 json:type="number">47</__1> <__2 json:type="number">34</__2> </Age> </customer> </Items>
これでは、Mapping においても・・・先ほどと同じく扱いにくいですよね。
そこで、今度は以下のようなXSL を通して「扱いやすい形」に変換します。この例では、/Items/customer/Id 配下のノードを対象に、ノード名を条件としてName/Gender/Age それぞれのノード配下から同じノード名の値を取得してcustomer として変換しています。
<?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" indent="yes" /> <xsl:template match="/Items/customer/Id/*"> <xsl:variable name="i" select="name()"/> <customer> <Id><xsl:value-of select="current()" /></Id> <Name><xsl:value-of select="../../Name/*[name()=$i]" /></Name> <Gender><xsl:value-of select="../../Gender/*[name()=$i]" /></Gender> <Age><xsl:value-of select="../../Age/*[name()=$i]" /></Age> </customer> </xsl:template> <xsl:template match="/Items/customer/Name"/> <xsl:template match="/Items/customer/Gender"/> <xsl:template match="/Items/customer/Age"/> <xsl:template match="/*"> <Items> <xsl:apply-templates /> </Items> </xsl:template> </xsl:stylesheet>
JSON コネクタでXML に変換したデータが、このXSL を指定したXSLT コネクタを通過すると、以下のようなXML に変換されます。
<?xml version="1.0" encoding="utf-8"?> <Items> <customer> <Id>1</Id> <Name>John</Name> <Gender>M</Gender> <Age>21</Age> </customer> <customer> <Id>2</Id> <Name>Tom</Name> <Gender>M</Gender> <Age>47</Age> </customer> <customer> <Id>3</Id> <Name>Jane</Name> <Gender>F</Gender> <Age>34</Age> </customer> </Items>
そうすれば、先の2つのフローと同じ「扱いやすいデータ構造」を相手にできますので、後続のフローも素直で簡単ですね。
おわりに
この記事では、奇妙なレスポンス形式を持つAPI と連携する(連携しなければならなくなった)時を例に、ArcESB のXSLT コネクタをご紹介しました。
ArcESB はシンプルで拡張性の高いコアフレームワークに、豊富なMFT・EDI・エンタープライズコネクタを備えたパワフルな製品です。CData Drivers との組み合わせで250を超えるアプリケーションへの連携を実現できます。必要な連携を低価格からはじめられる事も大きな特長です。
皆さんのつなぎたいシナリオでぜひ ArcESB を試してみてください。
お試しいただく中で何かご不明な点があれば、テクニカルサポートへお気軽にお問い合わせください。
この記事では ArcESB™ 2021 - 21.0.8054
を利用しています。