153.7. XJ エンドポイントの使用
153.7.1. JSON から XML への変換 リンクのコピーリンクがクリップボードにコピーされました!
次のルートでは、xslt スタイルシートが指定されていないため、メッセージの "identity" 変換が行われます。XML から XML に変換する場合、"Identity" 変換は、出力ドキュメントが入力ドキュメントの単なるコピーであることを意味します。XJ の場合、json ドキュメントを同等の XML 表現に変換することを意味します。
from("direct:start").
to("xj:identity?transformDirection=JSON2XML");
例:
入力:
{
"firstname": "camel",
"lastname": "apache",
"personalnumber": 42,
"active": true,
"ranking": 3.1415926,
"roles": [
"a",
{
"x": null
}
],
"state": {
"needsWater": true
}
}
出力:
<?xml version="1.0" encoding="UTF-8"?>
<object xmlns:xj="http://camel.apache.org/component/xj" xj:type="object">
<object xj:name="firstname" xj:type="string">camel</object>
<object xj:name="lastname" xj:type="string">apache</object>
<object xj:name="personalnumber" xj:type="int">42</object>
<object xj:name="active" xj:type="boolean">true</object>
<object xj:name="ranking" xj:type="float">3.1415926</object>
<object xj:name="roles" xj:type="array">
<object xj:type="string">a</object>
<object xj:type="object">
<object xj:name="x" xj:type="null">null</object>
</object>
</object>
<object xj:name="state" xj:type="object">
<object xj:name="needsWater" xj:type="boolean">true</object>
</object>
</object>
上記の出力に見られるように、XJ は結果である XML にメタデータを書き込み、その後の処理で使用できるようにします。
-
XJ メタデータノードは、必ず
http://camel.apache.org/component/xj名前空間にあります。 - JSON キー名は xj:name 属性に配置されます。
- 解析された JSON 型は、xj:type 属性にあります。上記の例には、考えられるすべての型が含まれています。
- 生成された XML 要素には、必ず "object" という名前が付けられます。
これで、次のようなスタイルシートを適用できるようになります。
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xj="http://camel.apache.org/component/xj"
exclude-result-prefixes="xj">
<xsl:output omit-xml-declaration="no" encoding="UTF-8" method="xml" indent="yes"/>
<xsl:template match="/">
<person>
<xsl:apply-templates select="//object"/>
</person>
</xsl:template>
<xsl:template match="object[@xj:type != 'object' and @xj:type != 'array' and string-length(@xj:name) > 0]">
<xsl:variable name="name" select="@xj:name"/>
<xsl:element name="{$name}">
<xsl:value-of select="text()"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*|node()"/>
</xsl:stylesheet>
上記のサンプルに適用するには、エンドポイントでテンプレートを指定します。
from("direct:start").
to("xj:com/example/json2xml.xsl?transformDirection=JSON2XML");
次のように出力されます。
<?xml version="1.0" encoding="UTF-8"?>
<person>
<firstname>camel</firstname>
<lastname>apache</lastname>
<personalnumber>42</personalnumber>
<active>true</active>
<ranking>3.1415926</ranking>
<x>null</x>
<needsWater>true</needsWater>
</person>
153.7.2. XML から JSON への変換 リンクのコピーリンクがクリップボードにコピーされました!
前述したとおり、スタイルシートが指定されていない場合は "identity" 変換が実行されます。
from("direct:start").
to("xj:identity?transformDirection=XML2JSON");
以下のサンプル入力を指定します。
<?xml version="1.0" encoding="UTF-8"?>
<person>
<firstname>camel</firstname>
<lastname>apache</lastname>
<personalnumber>42</personalnumber>
<active>true</active>
<ranking>3.1415926</ranking>
<roles>
<entry>a</entry>
<entry>
<x>null</x>
</entry>
</roles>
<state>
<needsWater>true</needsWater>
</state>
</person>
結果は以下のようになります。
{
"firstname": "camel",
"lastname": "apache",
"personalnumber": "42",
"active": "true",
"ranking": "3.1415926",
"roles": [
"a",
{
"x": "null"
}
],
"state": {
"needsWater": "true"
}
}
ここでは何も特別なことは行っていませんが、json から xml への変換において、入力 xml と出力 json が上記の例と非常に似ていることがわかります。任意の XML ドキュメントを json に変換しただけです。XJ は、デフォルトで次のルールを使用します。
- XML ルート要素には名前を付けることができ、必ず JSON ルートオブジェクト宣言 '\{}' で終わります。
- json キーの名前は xml 要素の名前です。
- 上記の "<roles>" のように、2 つの "<entry>" 要素が存在する場合に名前が競合する場合、json 配列が生成されます。
- テキストのみの子ノードを持つ XML 要素は、通常のキー/文字列値のペアになります。コンテンツ要素が混在する場合、上記の "<state>" のようにキー/子オブジェクトのペアが生成されます。
これで、以下の例のように、スタイルシートを再度適用できます。
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xj="http://camel.apache.org/component/xj"
exclude-result-prefixes="xj">
<xsl:output omit-xml-declaration="no" encoding="UTF-8" method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="personalnumber">
<xsl:element name="{local-name()}">
<xsl:attribute name="xj:type">
<xsl:value-of select="'int'"/>
</xsl:attribute>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="active|needsWater">
<xsl:element name="{local-name()}">
<xsl:attribute name="xj:type">
<xsl:value-of select="'boolean'"/>
</xsl:attribute>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="ranking">
<xsl:element name="{local-name()}">
<xsl:attribute name="xj:type">
<xsl:value-of select="'float'"/>
</xsl:attribute>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="roles">
<xsl:element name="{local-name()}">
<xsl:attribute name="xj:type">
<xsl:value-of select="'array'"/>
</xsl:attribute>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="*[normalize-space(text()) = 'null']">
<xsl:element name="{local-name()}">
<xsl:attribute name="xj:type">
<xsl:value-of select="'null'"/>
</xsl:attribute>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
エンドポイントでテンプレートを指定して、上記のサンプルに適用します。
from("direct:start").
to("xj:com/example/xml2json.xsl?transformDirection=XML2JSON");
次のように出力されます。
{
"firstname": "camel",
"lastname": "apache",
"personalnumber": 42,
"active": true,
"ranking": 3.1415926,
"roles": [
"a",
{
"x": null
}
],
"state": {
"needsWater": true
}
}
この変換により、json2xml 変換への入力として使用したものとまったく同じ json ドキュメントが生成されることに注意してください。次の XML ドキュメントが、xsl 変換の後に XJ に渡されます。
<?xml version="1.0" encoding="UTF-8"?>
<person>
<firstname>camel</firstname>
<lastname>apache</lastname>
<personalnumber xmlns:xj="http://camel.apache.org/component/xj" xj:type="int">42</personalnumber>
<active xmlns:xj="http://camel.apache.org/component/xj" xj:type="boolean">true</active>
<ranking xmlns:xj="http://camel.apache.org/component/xj" xj:type="float">3.1415926</ranking>
<roles xmlns:xj="http://camel.apache.org/component/xj" xj:type="array">
<entry>a</entry>
<entry>
<x xj:type="null">null</x>
</entry>
</roles>
<state>
<needsWater xmlns:xj="http://camel.apache.org/component/xj" xj:type="boolean">true</needsWater>
</state>
</person>
スタイルシートでは、同じ結果を得るために必要最小限の型ヒントのみを指定しました。サポートされている型ヒントは、json から xml への変換時に XJ が XML ドキュメントに書き込むものとまったく同じです。
これは、上記の JSON から XML への変換サンプルから結果のドキュメントをフィードバックできることを意味します。
<?xml version="1.0" encoding="UTF-8"?>
<object xmlns:xj="http://camel.apache.org/component/xj" xj:type="object">
<object xj:name="firstname" xj:type="string">camel</object>
<object xj:name="lastname" xj:type="string">apache</object>
<object xj:name="personalnumber" xj:type="int">42</object>
<object xj:name="active" xj:type="boolean">true</object>
<object xj:name="ranking" xj:type="float">3.1415926</object>
<object xj:name="roles" xj:type="array">
<object xj:type="string">a</object>
<object xj:type="object">
<object xj:name="x" xj:type="null">null</object>
</object>
</object>
<object xj:name="state" xj:type="object">
<object xj:name="needsWater" xj:type="boolean">true</object>
</object>
</object>
そうすることで、同じ出力を再度取得できます。
{
"firstname": "camel",
"lastname": "apache",
"personalnumber": 42,
"active": true,
"ranking": 3.1415926,
"roles": [
"a",
{
"x": null
}
],
"state": {
"needsWater": true
}
}
上記の例からわかるように、* xj:type では出力型を正確に指定でき、* xj:name では json キー名を却下できます。これは、XML 要素名で許可されていない文字を含むキー名を生成する場合に必要です。
153.7.2.1. 使用できる型ヒント リンクのコピーリンクがクリップボードにコピーされました!
| @xj:type= | 説明 |
|---|---|
| object | json オブジェクトを生成します |
| array | json 配列を生成します |
| string | JSON 文字列を生成します |
| int | 小数部分を除いた JSON 数値を生成します |
| float | 小数部分を含む JSON 数値を生成します |
| boolean | JSON ブール値を生成します |
| null | null という単語を使用して空の値を生成します |