149.7. 使用 XJ 端点
149.7.1. 将 JSON 转换为 XML 复制链接链接已复制到粘贴板!
以下路由执行消息的"身份"转换,因为未提供 xslt 风格表。在 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>
149.7.2. 将 XML 转换为 JSON 复制链接链接已复制到粘贴板!
在不提供风格表时,将根据以上说明执行"身份"转换:
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 altough 特殊操作时,输入 xml 和输出 json 与上述示例非常相似。我们仅将任意 XML 文档转换为 json。XJ 默认使用以下规则:
- XML root 元素可以进行命名,它始终以 json root 对象声明 '\{}' 结尾。
- json 键名称是 xml 元素的名称
- 如果上面"<roles>"中存在一个名称 clash,则会产生两个 "<entry>" 元素。
- 带有 text-only-child-nodes 的 XML 元素将导致通常的 key/string-value 对。混合内容元素会导致键/子对象对,如上面的 "<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
}
}
请注意,此转换会导致 json 文档与我们用于对 json2xml 转换的输入完全相同。以下 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 元素名称中不允许的字符的密钥名称时,需要此项。
149.7.2.1. 可用类型提示 复制链接链接已复制到粘贴板!
| @xj:type= | 描述 |
|---|---|
| object | 生成 json 对象 |
| 数组 | 生成 json 数组 |
| string | 生成 json 字符串 |
| int | 生成一个没有部分的 json 号 |
| 浮点值 | 使用部分部分生成 json 号 |
| 布尔值 | 生成 json 布尔值 |
| null | 使用单词 null 生成一个空值 |