XPath for Workday - xpath

I'm really new with XPath and would appreciate your expert advice!
<wd:Get_Workers_Response xmlns:wd="urn:com.workday/bsvc" wd:version="v24.1">
<wd:Response_Data>
<wd:Worker>
<wd:Worker_Data>
<wd:Employment_Data>
<wd:Position_Data wd:Effective_Date="2022-04-17-07:00">
<wd:Job_Classification_Summary_Data>
<wd:Job_Classification_Reference wd:Descriptor="Some Value">
<wd:ID wd:type="WID">6abcdefghijklmnopqrstuvwxyzabcd2</wd:ID>
<wd:ID wd:type="Job_Classification_Reference_ID">Some_Value</wd:ID>
</wd:Job_Classification_Reference>
<wd:Job_Group_Reference wd:Descriptor="MIP">
<wd:ID wd:type="WID">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</wd:ID>
<wd:ID wd:type="Job_Classification_Group_ID">JOB_CLASSIFICATION_GROUP_MIP</wd:ID>
</wd:Job_Group_Reference>
</wd:Job_Classification_Summary_Data>
</wd:Position_Data>
</wd:Employment_Data>
</wd:Worker_Data>
</wd:Worker>
</wd:Response_Data>
</wd:Get_Workers_Response>
I'd like to get the value "Some_value" in
<wd:ID wd:type="Job_Classification_Reference_ID">Some_Value</wd:ID>
where WID=6abcdefghijklmnopqrstuvwxyzabcd2
Can you tell me the xpath for that?

This XPath expression:
string(//wd:ID[#wd:type = 'Job_Classification_Reference_ID']/text())
when evaluated against the provided XML document (with added arbitrary namespace-uri for the prefix 'wd:' to make it wellformed):
<wd:Response_Data xmlns:wd="urn:com.workday/xxx">
<wd:Worker>
<wd:Worker_Data>
<wd:Employment_Data>
<wd:Position_Data wd:Effective_Date="2022-04-17-07:00">
<wd:Job_Classification_Summary_Data>
<wd:Job_Classification_Reference wd:Descriptor="Some Value">
<wd:ID wd:type="WID">6abcdefghijklmnopqrstuvwxyzabcd2</wd:ID>
<wd:ID wd:type="Job_Classification_Reference_ID">Some_Value</wd:ID>
</wd:Job_Classification_Reference>
<wd:Job_Group_Reference wd:Descriptor="MIP">
<wd:ID wd:type="WID">XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</wd:ID>
<wd:ID wd:type="Job_Classification_Group_ID">JOB_CLASSIFICATION_GROUP_MIP</wd:ID>
</wd:Job_Group_Reference>
</wd:Job_Classification_Summary_Data>
</wd:Position_Data>
</wd:Employment_Data>
</wd:Worker_Data>
</wd:Worker>
</wd:Response_Data>
Selects the string value of the wanted text node:
Some_Value
Do note:
In your XPath engine you need to register a 'wd:' prefix and associate it with the "urn:com.workday/xxx" namespace.

When you can declare a prefix for the used namespace use this XPath:
//wd:ID[#wd:type='WID' and text()='6abcdefghijklmnopqrstuvwxyzabcd2']/following-sibling::wd:ID[1]/text()
Or as an faster alternative while the XPath is more explicit, use this XPath:
//wd:Job_Classification_Summary_Data/wd:Job_Classification_Reference[wd:ID[#type='WID']/text() = '6abcdefghijklmnopqrstuvwxyzabcd2']]/wd:ID[#type='Job_Classification_Reference_ID']/text()
If you are not able do use a prefix use this XPath:
//*[local-name()='ID'][#*[local-name()='type' and .='WID'] and text()='6abcdefghijklmnopqrstuvwxyzabcd2']/following-sibling::*[local-name()='ID'][1]/text()

Related

XPath as a string variable / property

I retrieve XPath from a database (via DSS) and I need to apply it to the body. Is this somehow possible?
To give an example, let's say I have this xml request
<custom>
<id>24</id>
<text>Some Text</text>
<firstOccurId>123456</firstOccurId>
<secondOccurId>654321</secondOccurId>
</custom>
I take ID (24) and call template, which will return
<replacements>
<row>
<value>ABCDEFG</value>
<xpath>/*/custom/firstOccurId</xpath>
</row>
<row>
<value>GFEDCDBA</value>
<xpath>/*/custom/secondOccurId</xpath>
</row>
</replacements>
now I need to apply xpath to request and change it's value, so the transformed request body looks like this
<custom>
<id>24</id>
<text>Some Text</text>
<firstOccurId>ABCDEFG</firstOccurId>
<secondOccurId>GFEDCDBA</secondOccurId>
</custom>
I tried both evaluate() and put XPath string inside {{}} in Call Template mediator, but both without success.
evaluate() is the correct answer. To be more specific, for this example I need to store custom request in property, get replacements, loop through them and inside this loop I need to store full xpath in property as fn:concat('$body', //el:row/el:xpath, '/text()'), enrich body with original payload and apply stored xpath as evaluate()

XPath to only select the text contained within an element

I am new to xpath so I apologize in advance for how basic this question is.
How do I extract just the text from a specific element? For example, how would I extract just "text"
<h1>text</h1>
I tried the following but it seems to select everything including the tags instead of just the text.
//h1/text()
Thanks for your help
`
DocumentBuilderFactory docFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(new File("src/myFile.xml"));
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
String sessionId = (String) xpath
.evaluate(
"/Envelope/Body/LoginProcessResponse/loginResponse/sessionId",
doc, XPathConstants.STRING);
`
here Envelope is my parent element and i just traversed to the required path(in my case it is sessionid).
Hope it helps
This answer is rather an XSLT answer than an XPath answer, but many of the concepts are nevertheless applicable.
The XPath expression
//h1/text()
seems to be correct. It does select all text() nodes that are direct children of <h1> elements.
But one problem may be, that the XSL default template still copies all the othertext() nodes like described here in the W3C specification:
In the absence of a select attribute, the xsl:apply-templates instruction processes all of the children of the current node, including text nodes.
So to solve your problem, you have to define an explicit template that
ignores all other text() nodes like this:
<xsl:template match="text()" />
If you add this line to your XSL processing, the result will most likely be more pleasant to you.

using mule variable value in xpath expression

I have a variable set as
<set-variable variableName="productIdvar" value="#[xpath://productId]" doc:name="Variable" />
On logging its coming right,
I want to use the value of the variable productIdvar in my xpath expression,
<when expression="//*[local-name()='itemid']=?" evaluator="xpath">
or
<when expression="#[xpath://*[local-name()='itemid']=?]">
What should i use in place of ? to get the value of the variable?
Thanks
Rahul.
The following expression should work for you.
<when expression="#[xpath('//*[local-name()=\'itemid\']').text == productIdvar ]">
This way you should be able to compare the result of the xpath with the "productIdVar" variable.
Hope this helps.
<when expression="#[xpath('//*[local-name()=itemid]') == productIdvar ]">
Note that there are no quotation marks surrounding itemid in expression
If your MEL gets a bit messy, try my mule-module-dxpath - an XPath transformer which dynamicaly resolves XPath variables.
You can use XPATH3 and try something like this
#[xpath3('/products/validlity')== flowVars.productIdvar]
Xpath3 reference :- https://developer.mulesoft.com/docs/display/current/XPath

Get attribute value from XML

I have this chunk of XML:
<show name="Are We There Yet?">
<sid>24588</sid>
<network>TBS</network>
<title>The Kwandanegaba Children's Fund Episode</title>
<ep>03x31</ep>
<link>
http://www.tvrage.com/shows/id-24588/episodes/1065228407
</link>
</show>
I am trying to get "Are we there yet?" via Nokogiri. It is effectively the 'name' attribute of 'show'. I'm struggling to figure out how to parse this.
xml.at_css('show').value was my best guess but doesn't work.
You can use the following:
xml.at('//show/#name').text
which is XPath expression that returns the name attribute from the show element.
Use:
require 'nokogiri'
xml =<<EOT
<show name="Are We There Yet?">
<sid>24588</sid>
<network>TBS</network>
<title>The Kwandanegaba Children's Fund Episode</title>
<ep>03x31</ep>
<link>
http://www.tvrage.com/shows/id-24588/episodes/1065228407
</link>
</show>
EOT
xml = Nokogiri::XML(xml)
puts xml.at('show')['name']
=> Are We There Yet?
at accepts either CSS or XPath expressions, so feel free to use it for both. Use at_css or at_xpath if you know you need to declare the expression as CSS or XPath, respectively. at returns a Node, so you can simply reference the parameters of the node like you would a hash.

XPath query to match depending on combinations of child elements

I have the following Xml structure; Payment/Line which has amongst its element a IsFeePayment and a IsServiceProduct elements of type bool.
<Payment>
<Line>
<IsFeePayment>true</IsFeePayment>
<ISServiceProduct>true</IsServiceProduct>
</Line>
</Payment>
i want an xpath statement that returns 'true' when both of these are are they are, true.
if either one is false, i want the xpath statement to return 'false'
THe xpath below is almost there, it returns the line when both are true.
/[local-name()='Payment']/[local-name()='Line'][*[local-name()='IsFeePayment'][text()='true'] and *[local-name()='IsServiceProduct'][text()='true']]
how do i just get a simple bool out instead of the whole element?
You can simplify the xpath to
boolean(//Payment/Line[IsFeePayment='true' and IsServiceProduct='true'])
simply adding a boolean() around the xpath expression i already had fixes the problem blush
so ...
boolean(/[local-name()='Payment']/[local-name()='Line'][*[local-name()='IsFeePayment'][text()='true'] and *[local-name()='IsServiceProduct'][text()='true']])

Resources