在 jboss 熔断器中将 xml 的子记录拆分为 activeMQ 中的单独消息

Split the child records of xml into individual messages in activeMQ in jboss fuse

这是一个jboss熔断器项目

我有这样的场景,其中一个文件有 1 个 XML 和多个子记录。我需要拆分子记录并使用 XSLT 将其转换为多个 XML . 示例 XML 订单(输入):

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <cd>
    <title>Empire Burlesque</title>
    <artist>Bob Dylan</artist>
    <country>USA</country>
    <company>Columbia</company>
    <price>10.90</price>
    <year>1985</year>
  </cd>
  <cd>
    <title>Hide your heart</title>
    <artist>Bonnie Tyler</artist>
    <country>UK</country>
    <company>CBS Records</company>
    <price>9.90</price>
    <year>1988</year>
  </cd>
  
</catalog>

我有这个 XSLT :

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="/">
  <!-- TODO: Auto-generated template -->
  <xsl:for-each select="catalog/cd">
            <xsl:result-document href="file{position()}.xml">
                <document>
                    <xsl:copy-of select="current()"/>
                </document>
            </xsl:result-document>
            
          
        </xsl:for-each>
        
 </xsl:template>
</xsl:stylesheet>

BLUEPRINT.xml(骆驼路线)

 <route id="_route1">
            <from id="_from1" uri="file:work/in"/>
            <log id="_log1" message="${body}"/>
            <loop id="_loop1">
                <xpath>count(/catalog/cd)</xpath>
                <to id="_to1" uri="xslt:file:C:\Users\a638030\workspace\splitxml\data\order1.xsl"/>
                <log id="_log2" message="${body}"/>
            </loop>
        </route>

当我运行这条路线时,它说错误如下:

[xt) thread #2 - file://work/in] _route1                        INFO  <?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <cd>
    <title>Empire Burlesque</title>
    <artist>Bob Dylan</artist>
    <country>USA</country>
    <company>Columbia</company>
    <price>10.90</price>
    <year>1985</year>
  </cd>
  <cd>
    <title>Hide your heart</title>
    <artist>Bonnie Tyler</artist>
    <country>UK</country>
    <company>CBS Records</company>
    <price>9.90</price>
    <year>1988</year>
  </cd>
  
</catalog>


[xt) thread #2 - file://work/in] XPathBuilder                   INFO  Created default XPathFactory com.sun.org.apache.xpath.internal.jaxp.XPathFactoryImpl@4b4289ed
[xt) thread #2 - file://work/in] DefaultErrorHandler            ERROR Failed delivery for (MessageId: ID-MC0WKB0C-60902-1513777570783-0-1 on ExchangeId: ID-MC0WKB0C-60902-1513777570783-0-2). Exhausted after delivery attempt: 1 caught: org.apache.camel.builder.xml.InvalidXPathExpression: Invalid xpath: count(/catalog/cd). Reason: javax.xml.xpath.XPathExpressionException: com.sun.org.apache.xpath.internal.XPathException: Can not convert #NUMBER to a NodeList!

Message History
---------------------------------------------------------------------------------------------------------------------------------------
RouteId              ProcessorId          Processor                                                                        Elapsed (ms)
[_route1           ] [_route1           ] [file://work/in                                                                ] [       270]
[_route1           ] [_log1             ] [log                                                                           ] [         7]
[_route1           ] [_loop1            ] [loop[xpath{XPath: count(/catalog/cd)}]                                        ] [       224]

Stacktrace
---------------------------------------------------------------------------------------------------------------------------------------
org.apache.camel.builder.xml.InvalidXPathExpression: Invalid xpath: count(/catalog/cd). Reason: javax.xml.xpath.XPathExpressionException: com.sun.org.apache.xpath.internal.XPathException: Can not convert #NUMBER to a NodeList!
 at org.apache.camel.builder.xml.XPathBuilder.doInEvaluateAs(XPathBuilder.java:916)
 at org.apache.camel.builder.xml.XPathBuilder.evaluateAs(XPathBuilder.java:780)
 at org.apache.camel.builder.xml.XPathBuilder.evaluate(XPathBuilder.java:750)
 at org.apache.camel.builder.xml.XPathBuilder.evaluate(XPathBuilder.java:165)
 at org.apache.camel.processor.LoopProcessor.process(LoopProcessor.java:64)
 at org.apache.camel.management.InstrumentationProcessor.process(InstrumentationProcessor.java:77)
 at org.apache.camel.processor.RedeliveryErrorHandler.process(RedeliveryErrorHandler.java:468)
 at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:196)
 at org.apache.camel.processor.Pipeline.process(Pipeline.java:121)
 at org.apache.camel.processor.Pipeline.process(Pipeline.java:83)
 at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:196)
 at org.apache.camel.component.file.GenericFileConsumer.processExchange(GenericFileConsumer.java:454)
 at org.apache.camel.component.file.GenericFileConsumer.processBatch(GenericFileConsumer.java:226)
 at org.apache.camel.component.file.GenericFileConsumer.poll(GenericFileConsumer.java:190)
 at org.apache.camel.impl.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:175)
 at org.apache.camel.impl.ScheduledPollConsumer.run(ScheduledPollConsumer.java:102)
 at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
 at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
 at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access1(ScheduledThreadPoolExecutor.java:180)
 at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 at java.lang.Thread.run(Thread.java:748)
Caused by: javax.xml.xpath.XPathExpressionException: com.sun.org.apache.xpath.internal.XPathException: Can not convert #NUMBER to a NodeList!
 at com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:204)
 at org.apache.camel.builder.xml.XPathBuilder.doInEvaluateAs(XPathBuilder.java:898)
 ... 22 more
Caused by: com.sun.org.apache.xpath.internal.XPathException: Can not convert #NUMBER to a NodeList!
 at com.sun.org.apache.xpath.internal.objects.XObject.error(XObject.java:711)
 at com.sun.org.apache.xpath.internal.objects.XObject.nodelist(XObject.java:457)
 at com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.getResultAsType(XPathExpressionImpl.java:364)
 at com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.eval(XPathExpressionImpl.java:110)
 at com.sun.org.apache.xpath.internal.jaxp.XPathExpressionImpl.evaluate(XPathExpressionImpl.java:191)
 ... 23 more
在此,它首先记录了我提供输入的 XML 文件,然后它给出了循环路径中 XPATH 表达式的错误。

那么你能帮我解决这个问题吗?或者对于这种情况还有其他方法吗?

场景:我有这样一个场景,其中一个文件有 1 个 XML 和多个子记录。我需要拆分子记录并使用 XSLT 将其转换为多个 XML(在 JBOSS FUSE 中)

你应该改变这个:

        <loop id="_loop1">
            <xpath>count(/catalog/cd)</xpath>
            <to id="_to1" uri="xslt:file:C:\Users\a638030\workspace\splitxml\data\order1.xsl"/>
            <log id="_log2" message="${body}"/>
        </loop>

进入这个:

        <split id="_split1">
            <xpath>/catalog/cd</xpath>
            <to id="_to1" uri="xslt:file:C:\Users\a638030\workspace\splitxml\data\order1.xsl"/>
            <log id="_log2" message="${body}"/>
        </split>

执行此操作时,每个 cd 元素将获得一次交换,因此您必须相应地更改 XSLT。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:param name="CamelSplitIndex" />

    <xsl:template match="/">
        <xsl:result-document href="file$CamelSplitIndex.xml">
            <document>
                <xsl:value-of select="."/>
            </document>
        </xsl:result-document>
    </xsl:template>
</xsl:stylesheet>

我建议你看看Splitter EIP

感谢@noMad17 的帮助。

(BLUEPRINT.XML)使用 ActiveMQ 的路由:

   <route id="_route1">
            <from id="_from1" uri="file:work/in"/>
            <log id="_log1" message="${body}"/>
            <split id="_split1">
                <xpath>/catalog/cd</xpath>
                <log id="_log3" message="split data :  ${body}"/>
                <to id="_to1" uri="xslt:file:C:\Users\a638030\workspace\Scenario5\data\order.xsl"/>
                <log id="_log2" message="After XSLT : ${body}"/>
                <to id="_to2" pattern="InOnly" uri="activemq:queue:OrderDetails"/>
            </split>
        </route>

XML 输入:

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <cd  >
    <title>Empire Burlesque</title>
    <artist>Bob Dylan</artist>
    <country>USA</country>
    <company>Columbia</company>
    <price>10.90</price>
    <year>1985</year>
  </cd>
  <cd>
    <title>Hide your heart</title>
    <artist>Bonnie Tyler</artist>
    <country>UK</country>
    <company>CBS Records</company>
    <price>9.90</price>
    <year>1988</year>
  </cd>
  
</catalog>

XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="/">
  <xsl:element name="catalog">
   <xsl:element name="cd">
    <xsl:copy-of select="/*[local-name()='cd']/*"/>
   </xsl:element>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

在 ACTIVEMQ 中输出消息:

Message 1 :

<?xml version="1.0" encoding="UTF-8"?><catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan</artist><country>USA</country><company>Columbia</company><price>10.90</price><year>1985</year></cd></catalog>

Message 2: 

<?xml version="1.0" encoding="UTF-8"?><catalog><cd><title>Hide your heart</title><artist>Bonnie Tyler</artist><country>UK</country><company>CBS Records</company><price>9.90</price><year>1988</year></cd></catalog>