我们有一个用例,我们需要从多个源构建master xml。最初我们将从服务获取xml并使用来自此xml的信息,我们进行不同的数据库调用以保存/获取信息,最后构建master xml并保存到数据库。我们正在使用带保险丝的骆驼。
Here is our xml and camel routes.
<xml>
<xmlInformation>
.....
</xmlInformation>
<customers>
<customer>...</customer>
<customer>...</customer>
<customer>...</customer>
</customers>
<products>
<product>....<product>
<product>....<product>
<product>....<product>
</products>
</xml>
客户和产品元素的数量是动态的,我们从xml中提取每个客户,产品,保存到数据库并获取一些客户,产品相关的ID并构建master xml,如下所示。
<m:master>
<m:xmlInformation>....</m:xmlInformation>
<c:customers>
<c:customer id="12345">....</c:customer>
<c:customer id="22345">....</c:customer>
<c:customer id="32345">....</c:customer>
</c:customers>
<p:products>
<p:product id="22222">.....</p:product>
<p:product id="11111">.....</p:product>
<p:product id="33333">.....</p:product>
</p:products>
</m:master>
Here is came route
<route id="routeA">
<from uri="direct-vm:saveMasterXml" />
<setProperty propertyName="originalIUPayload"><simple>${body}</simple></setProperty>
<splitter parallelProcessing=true stopOnException=true strategyRef="customersAggregator" >
<xpath>/xml/customers/customer</xpath>
<bean ref="customerService" method="saveCustomer" />
</splitter>
<setProperty propertyName="customerXmls"><simple>${body}</simple></setProperty>
<setBody><simple>${property.originalIUPayload}</simple></setBody>
<splitter parallelProcessing=true stopOnException=true strategyRef="productsAggregator" >
<xpath>/xml/products/product</xpath>
<bean ref="productService" method="getProductIds" />
</splitter>
<setProperty propertyName="productIds"><simple>${body}</simple></setProperty>
<setBody><simple>${property.originalIUPayload}</simple></setBody>
<!-- transformation -->
<bean ref="masterService" method="saveMasterXml" />
</route>
客户分配器的输出是富含ID的客户xml列表,产品分配器的输出是产品ID列表。我可以使用xslt构建master xml,因为master xml的大多数元素都是原始xml,但客户和产品列表中的ID需要传递给xslt。我被困在这里解决它。欢迎任何建议。
答案 0 :(得分:0)
我使用.splitter()然后使用.end(),然后再次获得原始消息。
由于您要保存到数据库,因此在拆分之前可能需要.transacted()。有关交易的更多信息,请查看“Camel In Action”一书。
而不是记录拆分消息的主体,而不是为客户或产品调用bean
参见示例:
import org.apache.camel.EndpointInject;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.test.junit4.CamelTestSupport;
import org.junit.Test;
public class SplittingToXSLT extends CamelTestSupport {
@EndpointInject(uri = "direct:start")
private ProducerTemplate start;
@Test
public void testName() throws Exception {
context.addRoutes(new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:start")
.split(xpath("/xml/customers/customer | /xml/products/product"))
.choice()
.when(xpath("/customer"))
.log("Customer ${body}")
.when(xpath("/product"))
.log("Product ${body}")
.end()
.log("${body}")
.to("xslt:test.xsl")
.log("${body}")
;
}
});
start.sendBody("<xml>\n" +
" <xmlInformation>\n" +
" </xmlInformation>\n" +
" <customers>\n" +
" <customer>1</customer>\n" +
" <customer>2</customer>\n" +
" </customers>\n" +
" <products>\n" +
" <product>3</product>\n" +
" <product>4</product>\n" +
" </products>\n" +
"</xml>");
Thread.sleep(2000);
}
}
我不知道xslt中的命名空间是如何工作的,但这里有一个没有的例子:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<master>
<xmlInformation>
<xsl:value-of select="/xml/xmlInformation"/>
</xmlInformation>
<customers>
<xsl:for-each select="/xml/customers/customer">
<customer>
<xsl:attribute name="id">
<xsl:value-of select="."/>
</xsl:attribute>
</customer>
</xsl:for-each>
</customers>
<products>
<xsl:for-each select="/xml/products/product">
<product>
<xsl:attribute name="id">
<xsl:value-of select="."/>
</xsl:attribute>
</product>
</xsl:for-each>
</products>
</master>
</xsl:template>
</xsl:stylesheet>