1
votes

I'm trying to use xpath in a Mule flow to select the attribute 'value' under element Host based on the current value of element Stage (which will be in a Mule variable)

Here's the XML resource file feedHosts.xml

    <?xml version="1.0"?>
    <FeedHosts xmlns:bar="http://www.bar.org" xmlns:foo="http://www.foo.org/">
         <Host value="host1.com">
             <Stage>qa</Stage>
         </Host>
         <Host value="host2.com">
             <Stage>dev</Stage>
         </Host>
         <Host value="host3.com">
              <Stage>live</Stage>
         </Host>
     </FeedHosts> 

I've tried a few things like

    <set-payload value="#[groovy: getClass().getResourceAsStream('/feedHosts.xml')]" doc:name="Set Payload to feedHosts.xml"/>
    <byte-array-to-string-transformer doc:name="Byte Array to String"/>
    <mulexml:xpath-extractor-transformer name="whatever" expression="/FeedHosts/Host[Stage='#[flowVars.stage]']" resultType="NODE"/>
    <logger message="#[payload]" level="INFO" doc:name="Logger"/>

This does load feedHosts.xml into the payload but the xpath-extractor-transformer itself returns a null payload. Obviously it won't return the value attribute I want.

Any help appreciated.

3
What does <logger message="#[flowVars.stage]" level="INFO" doc:name="Logger"/> output? - Marcus Rickert
#[flowVars.stage] is the string 'qa' - kurt steele

3 Answers

2
votes

An XPath location path contains several steps which provide context. The last one selects data.

The last step of your expression selects a set of all Host elements in the context of /FeedHosts. The predicate restricts that set to the ones that have a Stage child element containing the text returned by #[flowVars.stage].

I'm not familiar with the Mule variable interpolation syntax. Assuming that the value #[flowVars.stage] actually produces one of the strings qa, dev or live, it should select one of the Host elements.

But you said you actually want to "select the attribute 'value' under element Host based on the current value of element Stage". In this case the last step should be in the attribute axis, and the Hosts set is only your context. You need to add one extra step:

/FeedHosts/Host[Stage=#[flowVars.stage]]/@value

For the interpolation syntax above, I referred to this reference

0
votes

This example returns the desired node and attribute (thanks helderdarocha) and also executes the query via an expression-transformer. The xpath-extractor-transformer expression won't accept the # character but expression-transformer will.

<set-payload value="#[groovy: getClass().getResourceAsStream('/hostsfile.xml')]" />
<set-variable variableName="myXPath" value="/FeedHosts/Host[Stage='#[stage]']/@value" />

<enricher target="#[flowVars.host]" doc:name="Message Enricher">
     <expression-transformer expression="#[xpath(myXPath).value]" />
</enricher>

<logger message="host is #[host]" level="INFO" doc:name="Logger"/>
0
votes

Since you XML has namespace associated with it, so you need to use Mule namespace manger to extract the values using Xpath
https://developer.mulesoft.com/ docs/display/current/XML+Namespaces
Something like the following :-

<mulexml:namespace-manager includeConfigNamespaces="true">
   <mulexml:namespace prefix="foo" uri="http://www.foo.org/"/>
   <mulexml:namespace prefix="bar" uri="http://www.bar.org"/>
</mulexml:namespace-manager> 

Then you can get the values in your Xpath, https://developer.mulesoft.com/docs/display/current/XML+Module+Reference