0

我们有一个用例,我们需要从多个来源构建主 xml。最初,我们将从服务中获取一个 xml,并使用来自该 xml 的信息进行不同的数据库调用以保存/获取信息,最后构造主 xml 并保存到数据库。我们正在使用带有 Fuse 的骆驼。

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 并构建主 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 来构造主 xml,因为主 xml 的大多数元素都是原始 xml,但是来自客户和产品列表的 id 需要传递给 xslt。我被困在这里解决它。欢迎任何建议。

4

1 回答 1

0

I used .splitter() and then .end(), then again you get the original message.

Since you are saving to a database, you would probably want a .transacted() before the splitting. Take a look in the book "Camel In Action" for more info about transactions.

And instead of logging the body of the splitted message you could call the bean for customer or product

See example:

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);
    }

}

I dont know how namespace in xslt works, but here's an example without:

<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>
于 2015-04-22T11:59:32.223 回答