无法使用 XPATH 设置 header

Not able to set header using XPATH

我有一个场景,我正在拆分 xml 并将它们发送到 activemq,然后想要记录 header orderid 和区域。为了获取区域,我使用了 java 方法:

        import org.apache.camel.language.NamespacePrefix;
        import org.apache.camel.language.XPath;

        /**
         * This class contains business logic that determines the region for a country. It is used by the Camel route in this example.
         */
        public class RegionSupport {

            public static final String AMER = "AMER";
            public static final String APAC = "APAC";
            public static final String EMEA = "EMEA";

            /**
             * Get the region code that corresponds to the given country code.
             * 
             * This method can be used as a plain Java method. However, when it is used inside a Camel route, the @XPath annotation will
             * evaluate the XPath expression and use the result as the method parameter. In this case, it will fetch the country code
             * from the order XML message. So, the method will determine the region code for the country that is in the XML message.
             * 
             * @param country the country code
             * @return the region code
             */
            public String getRegion(@XPath(value = "/order:order/order:customer/order:country",


     String country) {
                if (country.equals("AU")) {
                    return APAC;
                } else if (country.equals("US")) {
                    return AMER;
                } else {
                    return EMEA;
                }
            }
        }

XML 输入:

因此,按照以下 xml 我应该在第一个 Exchange

中将 header 记录为 id =2012_0001 Region = APAC
<?xml version="1.0" encoding="UTF-8"?>
<orders>
    <order id="2012_0001">

        <customer id="A0001">
            <name>Antwerp Zoo</name>
            <city>Antwerp</city>
            <country>AU</country>
        </customer>

        <date>2012-03-01</date>

        <orderlines>
            <orderline>
                <article id="A0001">
                    <description>Aardvark</description>
                </article>
                <quantity>1</quantity>
            </orderline>
            <orderline>
                <article id="A0011">
                    <description>Alpaca</description>
                </article>
                <quantity>10</quantity>
            </orderline>
        </orderlines>
    </order>
    <order id="2012_0002">

        <customer id="B0002">
            <name>Bristol Zoo Gardens</name>
            <city>Bristol</city>
            <country>UK</country>
        </customer>

        <date>2012-03-02</date>

        <orderlines>
            <orderline>
                <article id="B0002">
                    <description>Badger</description>
                </article>
                <quantity>2</quantity>
            </orderline>
            <orderline>
                <article id="B0202">
                    <description>Bee</description>
                </article>
                <quantity>200</quantity>
            </orderline>
        </orderlines>
    </order>
    </orders>

XSLT:

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

我的骆驼路线:

<route id="Splitter_Route">
            <from id="_from2" uri="direct:Splitter"/>
            <log id="_log6" message="Recieved file to split  : ${file:name}"/>
            <split id="_split1">
                <xpath>/orders/order</xpath>
                <log id="_log3" message="split data :  ${body}"/>
                <to id="_to1" uri="xslt:file:F:\jboss_workspace\ZooPattern\data\order.xsl"/>
                <log id="_log2" message="After XSLT : ${body} "/>
                <to id="_to2" uri="activemq:queue:zoodata"/>
                <log id="_log7" message="${body}"/>
                <setHeader headerName="orderId" id="_setHeader1">
                    <xpath resultType="java.lang.String">/order:order/@id</xpath>
                </setHeader>
                <setHeader headerName="region" id="_setHeader2">
                    <method bean="MyRegionSupport" method="getRegion"/>
                </setHeader>
                <log id="_log9" message="[splitter] Shipping order ${header.orderId}"/>
            </split>
        </route>

ERROR_Output :

所以我在 activemq 之前得到了正确的输出。在 Activemq logid7 未在 xml 中给出订单 ID 之后。然后它给出如下错误。 请让我知道哪里出错了。

    thread #2 - file://zoodata/in] Splitter_Route                 INFO  split data :  <order id="2012_0001">

            <customer id="A0001">
                <name>Antwerp Zoo</name>
                <city>Antwerp</city>
                <country>BE</country>
            </customer>

            <date>2012-03-01</date>

            <orderlines>
                <orderline>
                    <article id="A0001">
                        <description>Aardvark</description>
                    </article>
                    <quantity>1</quantity>
                </orderline>
                <orderline>
                    <article id="A0011">
                        <description>Alpaca</description>
                    </article>
                    <quantity>10</quantity>
                </orderline>
            </orderlines>
        </order>
    [ thread #2 - file://zoodata/in] Splitter_Route                 INFO  After XSLT : <?xml version="1.0" encoding="UTF-8"?><orders>
    <order>
    <customer id="A0001">
                <name>Antwerp Zoo</name>
                <city>Antwerp</city>
                <country>BE</country>
            </customer>
    <date>2012-03-01</date>
    <orderlines>
                <orderline>
                    <article id="A0001">
                        <description>Aardvark</description>
                    </article>
                    <quantity>1</quantity>
                </orderline>
                <orderline>
                    <article id="A0011">
                        <description>Alpaca</description>
                    </article>
                    <quantity>10</quantity>
                </orderline>
            </orderlines>
    </order>
    </orders>

    [ thread #2 - file://zoodata/in] Splitter_Route                 INFO  <?xml version="1.0" encoding="UTF-8"?><orders>
    <order>
    <customer id="A0001">
                <name>Antwerp Zoo</name>
                <city>Antwerp</city>
                <country>BE</country>
            </customer>
    <date>2012-03-01</date>
    <orderlines>
                <orderline>
                    <article id="A0001">
                        <description>Aardvark</description>
                    </article>
                    <quantity>1</quantity>
                </orderline>
                <orderline>
                    <article id="A0011">
                        <description>Alpaca</description>
                    </article>
                    <quantity>10</quantity>
                </orderline>
            </orderlines>
    </order>
    </orders>

[ thread #2 - file://zoodata/in] DefaultErrorHandler            ERROR Failed delivery for (MessageId: ID-LAPTOP-OO1BQC0T-63587-1514125730408-0-37 on ExchangeId: ID-LAPTOP-OO1BQC0T-63587-1514125730408-0-38). Exhausted after delivery attempt: 1 caught: org.apache.camel.builder.xml.InvalidXPathExpression: Invalid xpath: /order:order/@id. Reason: javax.xml.xpath.XPathExpressionException: com.sun.org.apache.xpath.internal.domapi.XPathStylesheetDOM3Exception: Prefix must resolve to a namespace: order

    Message History
    ---------------------------------------------------------------------------------------------------------------------------------------
    RouteId              ProcessorId          Processor                                                                        Elapsed (ms)
    [_route1           ] [_route1           ] [file://zoodata/in                                                             ] [        82]
    [Splitter_Route    ] [_log3             ] [log                                                                           ] [         0]
    [Splitter_Route    ] [_to1              ] [xslt:file:F:\jboss_workspace\ZooPattern\data\order.xsl                        ] [        15]
    [Splitter_Route    ] [_log2             ] [log                                                                           ] [         0]
    [Splitter_Route    ] [_to2              ] [activemq:queue:zoodata                                                        ] [        67]
    [Splitter_Route    ] [_log7             ] [log                                                                           ] [         0]
    [Splitter_Route    ] [_setHeader1       ] [setHeader[orderId]                                                            ] [         0]

    Stacktrace
    ---------------------------------------------------------------------------------------------------------------------------------------
    org.apache.camel.builder.xml.InvalidXPathExpression: Invalid xpath: /order:order/@id. Reason: javax.xml.xpath.XPathExpressionException: com.sun.org.apache.xpath.internal.domapi.XPathStylesheetDOM3Exception: Prefix must resolve to a namespace: order
        at org.apache.camel.builder.xml.XPathBuilder.evaluateAs(XPathBuilder.java:769)
        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.SetHeaderProcessor.process(SetHeaderProcessor.java:52)

错误说

Prefix must resolve to a namespace: order

这意味着您必须使用 <camelContext> 设置 XML 文件中的 order 命名空间。在那里你将它添加为属性

<camelContext .... xmlns:order="http://bla bla">

其中值是命名空间的唯一 uri,通常是一些网络 url。

但是您的 XML 输入不使用命名空间,因此您的问题是 setHeader 中的 xpath 正在使用它。但是你应该删除它并使用匿名 xpath,这应该是一个简单的修复

<xpath resultType="java.lang.String">/order:order/@id</xpath>

应该是

<xpath resultType="java.lang.String">/order/@id</xpath>

例如带冒号的 order: 是命名空间前缀,因此应将其删除。