Select node with same attribute name and but different values - xpath

I have the below xml document
<?xml version="1.0" encoding="UTF-8"?>
<xf:Report_Data xmlns:xf="urn:com.xforce.report/Job_History">
<xf:Report_Entry>
<xf:EmployeeID>11111</xf:EmployeeID>
<xf:Name xf:Descriptor="E Botha">
<xf:ID xf:type="XID">1111111111111</xf:ID>
<xf:ID xf:type="Employee_ID">22222</xf:ID>
</xf:Name>
<xf:RoleAssignedTo xf:Descriptor="Lena Johnson-Bey (51961)">
<xf:ID xf:type="WID">222222222222</xf:ID>
<xf:ID xf:type="Employee_ID">222222</xf:ID>
</xf:RoleAssignedTo>
<xf:RoleAssignedTo xf:Descriptor="Allison Sisk (21849)">
<xf:ID xf:type="XID">333333333333</xf:ID>
<xf:ID xf:type="Employee_ID">33333</xf:ID>
</xf:RoleAssignedTo>
</xf:Report_Entry>
</xf:Report_Data>
I need to extract the Employee_ID under the xf:RoleAssignedTo so I should get back 22222 and 33333. I tried the below xpath and I am only getting the first 22222:
/xf:Report_Data/xf:Report_Entry/xf:RoleAssignedTo/xf:ID[#xf:type='Employee_ID']
My goal is get back both 22222 and 33333. In some cases it could be more. I would greatly appreciate any help. I need to use xpath without resorting to xslt.

You can use the following way to extract the value of all Employee_ID using XPATH3:-
<http:listener-config name="HTTP_Listener_Configuration" host="0.0.0.0" port="8081" doc:name="HTTP Listener Configuration" />
<flow name="splitxml2Flow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/split" doc:name="HTTP"/>
<set-variable variableName="originalPayload" value="#[message.payloadAs(java.lang.String)]" doc:name="Variable"/>
<splitter expression="#[xpath3('//*:Report_Data/*:Report_Entry/*:RoleAssignedTo', message.payload, 'NODESET')]" doc:name="Splitter"/>
<logger level="INFO" message="Employee_ID:- #[xpath3('*:ID[2]')]" doc:name="Logger"/>
<collection-aggregator failOnTimeout="true" doc:name="Collection Aggregator"/>
<set-payload doc:name="Set Payload" value="Done"/>
</flow>
You will get all the value in logger as below:-
It will extract as many Employee_ID available in the XML

Related

how to use variable inside <xml-module:xpath-extract> mule 4

I have a variable set value as "Active." Based on the value of a variable, I want to select a node in the payload.
If I give values directly in xpath, it's work.
When I'm trying to use variables inside an xpath, like #Status = vars.xstatus. It returns a null value [].
Mule 4 flow:
<flow name="var_xpath_testFlow" doc:id="406270fb-17e7-48e9-a33a-f7a0197f8e05" >
<http:listener doc:name="Listener" doc:id="662f2277-859f-4516-974b-de7cceeb5b40" config-ref="HTTP_Listener_config" path="/vartest"/>
<set-variable value="Active" doc:name="Set Variable" doc:id="12370458-bb32-4709-b509-acc1e5f50b94" variableName="xstatus"/>
<xml-module:xpath-extract doc:id="6027ebad-f81d-4df1-8234-3d8dab04b129" config-ref="XML_Config" xpath="/DTOApplication/DTOLocation[#Status=vars.xstatus ]" target="xvalue"/>
<logger level="INFO" doc:name="Logger" doc:id="f495b0bf-f8cb-43be-b4d9-d069758e4028" message="#[vars.xvalue]"/>
</flow>
XPATH expression:
/DTOApplication/DTOLocation[#Status='Active']
XML payload: https://github.com/Manikandan99/rate-dtostep/blob/master/request.xml
how to use variables in XPath Mule 4?
Instead of a literal string use a Mule 4 expression.
Something like:
xpath="#["/DTOApplication/DTOLocation[#Status='" ++ vars.xstatus ++ "']"]"/>
I have edited your code, use below code that is having corrections for the xpath expression
<flow name="var_xpath_testFlow" doc:id="7490a882-4473-461d-846b-b6a7b65a8eca" >
<http:listener doc:name="Listener" doc:id="4767ed08-42cb-467c-80c2-4b739c68724e" config-ref="HTTP_Listener_config" path="/vartest"/>
<set-variable value="Active" doc:name="Set Variable" doc:id="62eaffcf-ea2e-4f05-8ad8-d840bbebe9e4" variableName="xstatus"/>
<xml-module:xpath-extract doc:id="15124867-b70c-4656-8eb9-d99d4e500a0e" config-ref="XML_Config" xpath='#["/DTOApplication/DTOLocation[#Status=" ++ vars.xstatus ++ "]"]' target="xvalue"/>
<logger level="INFO" doc:name="Logger" doc:id="340b9b89-18f8-4584-b6cb-7ab9d6d8efed" message="#[vars.xvalue]"/>
</flow>
Below is the screenshot that is showing how and where I did a correction
In the above screenshot as I Mentioned that click on "fx", if you add the expression without clicking on it and run your code, you will get an error as below
"Could not compile xpath expression "/DTOApplication/DTOLocation[#Status=" ++ vars.xstatus ++ "]""
In Mule 3, you must learn both the Mule Expression Language (MEL) and DataWeave. but now in Mule-4 DataWeave is the default expression language, if you click on "fx" it means you are entering DataWeave Expression Language
After this correction, I am getting correct output as in the below snippet
below is the complete xml file
<?xml version="1.0" encoding="UTF-8"?>
<mule
xmlns:xml-module="http://www.mulesoft.org/schema/mule/xml-module"
xmlns:http="http://www.mulesoft.org/schema/mule/http"
xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core"
xmlns:x12="http://www.mulesoft.org/schema/mule/x12"
xmlns="http://www.mulesoft.org/schema/mule/core"
xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/x12 http://www.mulesoft.org/schema/mule/x12/current/mule-x12.xsd
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/xml-module http://www.mulesoft.org/schema/mule/xml-module/current/mule-xml-module.xsd">
<http:listener-config name="HTTP_Listener_config"
doc:name="HTTP Listener config"
doc:id="5fe97da4-b1a9-4a9b-9a23-c4c42249fb2b">
<http:listener-connection host="0.0.0.0"
port="8081" />
</http:listener-config>
<xml-module:config name="XML_Config"
doc:name="XML Config" doc:id="6c8afa4c-6fec-4791-94a3-b4f8f63442e7" />
<flow name="var_xpath_testFlow"
doc:id="7490a882-4473-461d-846b-b6a7b65a8eca">
<http:listener doc:name="Listener"
doc:id="4767ed08-42cb-467c-80c2-4b739c68724e"
config-ref="HTTP_Listener_config" path="/vartest" />
<set-variable value="Active" doc:name="Set Variable"
doc:id="62eaffcf-ea2e-4f05-8ad8-d840bbebe9e4" variableName="xstatus" />
<xml-module:xpath-extract
doc:id="15124867-b70c-4656-8eb9-d99d4e500a0e" config-ref="XML_Config"
xpath='#["/DTOApplication/DTOLocation[#Status=" ++ vars.xstatus ++ "]"]'
target="xvalue" />
<logger level="INFO" doc:name="Logger"
doc:id="340b9b89-18f8-4584-b6cb-7ab9d6d8efed"
message="#[vars.xvalue]" />
</flow>
</mule>
Note: I am using Anypoint Studio version 7.11.1 ad Mule runtime version -4.4.0 (but I tried with runtime 4.3.0 and its working fine)

xpath 3 to XmlModule::xpath() in mule 4

I'm trying to migrate from Mule 3 to Mule 4.
XPATH3 is not supported in Mule 4.
I have xpath in Mule3:
xpath3('/DTOApplication/DTOLocation[#Status=\'Active\']',flowVars.domPayload,'NODESET')
Mule 3 flow:
<flow name="xpath_transformFlow">
<http:listener config-ref="HTTP_Listener_Configuration" path="/stepnode" allowedMethods="POST" doc:name="HTTP"/>
<set-variable variableName="dtolocation" value="#[xpath3('/DTOApplication/DTOLocation[#Status=\'Active\']',flowVars.domPayload,'NODESET')]" doc:name="set dtolocation"/>
<logger message="#[flowVars.dtolocation]" level="INFO" doc:name="Logger"/>
</flow>
xml payload : https://github.com/Manikandan99/rate-dtostep/blob/master/request.xml
I am trying xpath in mule 4 using #[XmlModule::xpath()] but its shows error.
Error message:
Script 'XmlModule::xpath('/DTOApplication/DTOLocation[#Status=\'Active\'],vars.domPayload,
{}) ' has errors: Invalid input ''', expected ')' for the function
call. (line 1, column 18): at 1 : 1" evaluating expression:
"#[XmlModule::xpath('/DTOApplication/DTOLocation[#Status=\'Active\'],vars.domPayload,
{})]".
Mule 4 flow:
<flow name="var_xpath_testFlow" doc:id="406270fb-17e7-48e9-a33a-f7a0197f8e05" >
<http:listener doc:name="Listener" doc:id="662f2277-859f-4516-974b-de7cceeb5b40" config-ref="HTTP_Listener_config" path="/vartest"/>
<set-variable value="#[payload]" doc:name="Set domPayload" doc:id="2495ac98-b976-41e0-9dcf-398574e54ffa" variableName="domPayload"/>
<set-variable value="#[XmlModule::xpath('/DTOApplication/DTOLocation[#Status=\'Active\'],vars.domPayload, {})]" doc:name="Set dtolocation_value" doc:id="3c751150-3606-4c40-9748-e658d9e6e59e" variableName="dtolocation_value"/>
<logger level="INFO" doc:name="Logger" doc:id="f495b0bf-f8cb-43be-b4d9-d069758e4028" message="#[vars.dtolocation_value]"/>
</flow>
How can I use it in mule 4?
The invocation to xpath() was missing a closing quote in the first parameter, after the first closing bracket. It looks like it is fixed in the expression but the error message is not updated.
Anyway after that I had an error because the function expects a Binary as the second argument. In my test the xpath-extract operation worked fine:
<xml-module:xpath-extract xpath="/DTOApplication/DTOLocation[#Status='Active']" doc:name="Xpath extract"/>
As an alternative I prefer to use DataWeave instead:
%dw 2.0
output application/xml
---
payload.DTOApplication filterObject ($$ as String == "DTOLocation" and $$.#Status == "Active")
Note that if you are using the output to perform further processing it would be preferred to output application/java.

Mule 3.9 - Unable to fetch xml value using foreach of Xpath3 NODESET

I am unable to retrieve the XML values using the below code snippet in Mule 3.9.5 and it works with the lower versions. I am looking for the solutions in XPath using foreach only not splitter as per my use-case.
Mule flow XML
<foreach collection="#[xpath3('/ParentData/Data', payload, 'NODESET')]">
Sample XML
<ParentData>
<Data>
<test1>value1</test1>
<test2>value2</test2>
</Data>
<Data>
<test1>value1</test1>
<test2>value2</test2>
</Data>
</ParentData>
Actual Output
[]
Expected Output
<Data>
<test1>value1</test1>
<test2>value2</test2>
</Data>
<Data>
<test1>value1</test1>
<test2>value2</test2>
</Data>
Any suggestions ?
Using xpath3() returns a list of nodes of the XML implemented with Java class net.sf.saxon.dom.DOMNodeList. For some reason it doesn't print the details of each node in a <logger>.
I think it is clearer, more intuitive, better documented and portable to future versions of Mule to use DataWeave script instead.
Example:
<dw:transform-message doc:name="Transform Message">
<dw:input-payload mimeType="application/xml" />
<dw:set-variable variableName="data"><![CDATA[
%dw 1.0
%output application/java
---
payload.ParentData.*Data
]]>
</dw:set-variable>
</dw:transform-message>
<foreach collection="#[flowVars.data]" doc:name="For Each">
<logger message="Data=#[payload]" level="INFO" doc:name="Logger"/>
</foreach>
Output:
Data={test1=value1, test2=value2}
Data={test1=value1, test2=value2}
In Mule 4 you can use the DataWeave expression directly in the <foreach>.

setting session variable available to all sessions of splitter

I have a situation where I am reading multiple files in one flow using collection aggregator. I then use a splitter to split the files to process one by one. Now, I want to put some elements of the file into a map and I want this map to be available to all sessions of splitter so that I can populate it for every file.
setting it withing the scope of file processing i.e after the splitter on makes it available to the current session of file processing. However, I was thinking of declaring the session variable as null before the splitter. Would that be available to all sessions after splitting?
I think it is as I saw for the first file process. I want to know also how to set the session variable as null. I didn't seem to find it. Also any other solution to the situation would be appreciated.
Here's my flow:
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:json="http://www.mulesoft.org/schema/mule/json"
xmlns:mulexml="http://www.mulesoft.org/schema/mule/xml"
xmlns:file="http://www.mulesoft.org/schema/mule/file" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.mulesoft.org/schema/mule/json http://www.mulesoft.org/schema/mule/json/current/mule-json.xsd
http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/current/mule-file.xsd">
<flow name="dictionary_keywordsFlow">
<file:inbound-endpoint path="D:\mJunction\CATALOG INTEGRATION TO BE MODIFIED\sOURCE FILES\Read_dir" connector-ref="Filefinal" pollingFrequency="10000" responseTimeout="10000" doc:name="File" moveToDirectory="D:\mJunction\CATALOG INTEGRATION TO BE MODIFIED\sOURCE FILES\Read_dir\backup">
<file:filename-regex-filter pattern="BSL.*" caseSensitive="true"/>
</file:inbound-endpoint>
<!-- <set-session-variable value="#[message.inboundProperties['originalFilename']]" variableName="filename" doc:name="Session Variable" /> -->
<set-property propertyName="MULE_CORRELATION_ID" value="#[message.inboundProperties['originalFilename']]" doc:name="Property"/>
<collection-aggregator failOnTimeout="true" doc:name="Collection Aggregator"/>
<!-- <custom-transformer class="AddContainerMapSessionvalue" doc:name="Java"/> -->
<splitter expression="#[payload]" doc:name="Splitter"/>
<logger message=">>> flow to extract keywords and create dictionary" level="INFO" doc:name="Logger"/>
<logger message="Payload received for maeterial list is #[payload]" level="INFO" doc:name="Original Payload"/>
<splitter expression="#[xpath3('//CATALOGUE',payload,'NODESET')]" doc:name="Splitter"/>
<mulexml:dom-to-xml-transformer doc:name="DOM to XML"/>
<json:xml-to-json-transformer doc:name="XML to JSON"/>
<json:json-to-object-transformer returnClass="java.util.Map" doc:name="JSON to Object"/>
<logger message="payload is #[payload]" level="INFO" doc:name="Logger"/>
<custom-transformer class="com.mjunction.transformers.DictionarykeywordsGenerator" doc:name="Java"/>
<logger message="payload is #[payload]" level="INFO" doc:name="Logger"/>
<logger message="session variable is #[sessionVars.container_map]" level="INFO" doc:name="Logger"/>
<json:object-to-json-transformer doc:name="Object to JSON"/>
<file:outbound-endpoint path="src/main/resources/dictionaryfiles/output" outputPattern="output.txt" connector-ref="Filefinal" responseTimeout="10000" doc:name="File"/>
</flow>
</mule>
Thanks,
Arun
You can define null session Variable as below
<set-session-variable variableName="fileName" value="#['']" doc:name="Session Variable"/>.
Yes, if you define session Variable before splitter and storing map( hoping you are getting this map from initial payload)will available through the session.
After splitter if you use session, everytime if the payload structure where you are extracting and storing in session is same, off- course it do override, such case you can use cache kind of concept. Refer: https://docs.mulesoft.com/mule-user-guide/v/3.7/cache-scope, or When you store it for the firstTime split and to use the case for the next sessions do a small condition check #[sessionVars['fileName'] != null? 'true':'']. Based on that you can construct the pending logic.

jms selector expression in Mule is not working

<flow name="readqueueFlow1" doc:name="readqueueFlow1" >
<jms:inbound-endpoint queue="MyTestQueue" connector-ref="Active_MQ-Priority" doc:name="JMS">
<jms:selector expression="JMSCorrelationID=’353’" />
</jms:inbound-endpoint>
</flow>
Its working but when i try to use the below one its not deploying
<!-- When we don't provide single quote it is failing in deployment -->
<jms:selector expression="JMSCorrelationID='#[flowVars.reqId]'" />
<!-- Payload contains reqId, when we provide it in single quote, it is assuming as a constant -->
<jms:selector expression="JMSCorrelationID='#[payload]'" />
I think here is your answer given :- Using an expression in a JMS Selector in Mule 3
And one more thing, you cannot use #[flowVars.reqId] for getting the jms:selector value dynamically since flow variable scope is limited to a flow ... instead use a session variable like #[sessionVars.reqId]..
and your flow will be modified as follow :-
<flow name="readqueueFlow1" >
<jms:inbound-endpoint queue="StudioOUT" connector-ref="Active_MQ" doc:name="JMS"/>
<scripting:component>
<scripting:script engine="groovy"><![CDATA[
def jmsMessages = []
for (def muleMessage = muleContext.client.request("jms://MyTestQueue?selector=JMSCorrelationID%3D'"+ sessionVars['reqId'] +"'", -1L);
muleMessage != null;) {
[] << muleMessage.payload
}
jmsMessages
]]></scripting:script>
</scripting:component>
<logger level="INFO" message="#[message.payload]" doc:name="Logger"/>
</flow>
You can see here the message is send to the queue using Groovy Script and I have used session variable instead of flow variable
jms:selector expression="putOnQueueTime > ABC "
can use the above expression in jms inbound.

Resources