使用 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