使用 Smooks 或 Groovy 与 Java Camel 到 split/transform XML
Using Smooks or Groovy with Java Camel to split/transform XML
Camel 版本 2.14 Smooks 版本 1.5.1
我收到一条消息,我想对其进行拆分和转换,但我需要来自父级的 id。所以我考虑使用 Smooks,拆分消息,转换并将每个输出发送到队列。它将使用 freemarker 模板进行转换。
<!-- Message -->
<data>
<id>123</id> <!-- This is needed in both portal messages -->
<portals>
<portal id="1" />
<portal id="2" />
</portals
</data>
<!-- Msg 1 -->
<portal dataId="123">
<id>1</id>
<portal>
<!-- Msg 2 -->
<portal dataId="123">
<id>2</id>
<portal>
有很多例子。但是例如,由于 "java.lang.ClassNotFoundException: org.apache.camel.component.ResourceBasedComponent" 这是一个已知问题,因此骆驼示例不起作用。
另一种方法是使用 groovy 进行转换?
那么,如何解决这个最简单的问题?
我不知道 smooks,但您可以将 XSLT 转换器与 XPATH 拆分器结合使用来完成此操作。
首先,将数据转换为构成每条消息的块。使用 XSLT、groovy 或任何您觉得舒服的方式来完成。这是一个简单的样式表,要放入 src/main/resources(或任何类路径位置)。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<portals>
<xsl:variable name="dataId" select="/data/id"/>
<xsl:for-each select="/data/portals/portal">
<portal dataId="$dataId">
<xsl:attribute name="dataId">
<xsl:value-of select="/data/id"/>
</xsl:attribute>
<id><xsl:value-of select="@id"/></id>
</portal>
</xsl:for-each>
</portals>
</xsl:template>
Camel 路线:首先是转换,然后是分离器。 "to" 可以是任何内容,例如用于进一步处理的 seda/direct 或目标协议。
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="file:data"/>
<to uri="xslt:transform.xslt"/>
<split>
<xpath>portals/portal</xpath>
<to uri="log:foo.bar?level=INFO"/>
</split>
</route>
在groovy中可以这样做:
import groovy.util.XmlSlurper
import groovy.xml.MarkupBuilder
def xml = """
<data>
<id>123</id>
<portals>
<portal id="1" />
<portal id="2" />
</portals>
</data>
"""
def slurped = new XmlSlurper().parseText(xml)
def msgId = slurped.id
def portalIds = slurped.portals.portal.@id*.text()
def portalXmls = portalIds.collect { portalId ->
writer = new StringWriter()
portalXml = new MarkupBuilder(writer)
portalXml.doubleQuotes = true
portalXml.portal(dataId: msgId) {
id(portalId)
}
writer
}.each { println it.toString() }
null
Camel 版本 2.14 Smooks 版本 1.5.1
我收到一条消息,我想对其进行拆分和转换,但我需要来自父级的 id。所以我考虑使用 Smooks,拆分消息,转换并将每个输出发送到队列。它将使用 freemarker 模板进行转换。
<!-- Message -->
<data>
<id>123</id> <!-- This is needed in both portal messages -->
<portals>
<portal id="1" />
<portal id="2" />
</portals
</data>
<!-- Msg 1 -->
<portal dataId="123">
<id>1</id>
<portal>
<!-- Msg 2 -->
<portal dataId="123">
<id>2</id>
<portal>
有很多例子。但是例如,由于 "java.lang.ClassNotFoundException: org.apache.camel.component.ResourceBasedComponent" 这是一个已知问题,因此骆驼示例不起作用。
另一种方法是使用 groovy 进行转换?
那么,如何解决这个最简单的问题?
我不知道 smooks,但您可以将 XSLT 转换器与 XPATH 拆分器结合使用来完成此操作。
首先,将数据转换为构成每条消息的块。使用 XSLT、groovy 或任何您觉得舒服的方式来完成。这是一个简单的样式表,要放入 src/main/resources(或任何类路径位置)。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<portals>
<xsl:variable name="dataId" select="/data/id"/>
<xsl:for-each select="/data/portals/portal">
<portal dataId="$dataId">
<xsl:attribute name="dataId">
<xsl:value-of select="/data/id"/>
</xsl:attribute>
<id><xsl:value-of select="@id"/></id>
</portal>
</xsl:for-each>
</portals>
</xsl:template>
Camel 路线:首先是转换,然后是分离器。 "to" 可以是任何内容,例如用于进一步处理的 seda/direct 或目标协议。
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="file:data"/>
<to uri="xslt:transform.xslt"/>
<split>
<xpath>portals/portal</xpath>
<to uri="log:foo.bar?level=INFO"/>
</split>
</route>
在groovy中可以这样做:
import groovy.util.XmlSlurper
import groovy.xml.MarkupBuilder
def xml = """
<data>
<id>123</id>
<portals>
<portal id="1" />
<portal id="2" />
</portals>
</data>
"""
def slurped = new XmlSlurper().parseText(xml)
def msgId = slurped.id
def portalIds = slurped.portals.portal.@id*.text()
def portalXmls = portalIds.collect { portalId ->
writer = new StringWriter()
portalXml = new MarkupBuilder(writer)
portalXml.doubleQuotes = true
portalXml.portal(dataId: msgId) {
id(portalId)
}
writer
}.each { println it.toString() }
null