使用多个输入构造xml

时间:2015-04-21 23:19:09

标签: java apache-camel xslt-2.0 jbossfuse smooks

我们有一个用例,我们需要从多个源构建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。我被困在这里解决它。欢迎任何建议。

1 个答案:

答案 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>