how to get node value by EvaluateXpath processor? - xpath

I have nifi processor EvaluateXpath and i want to get tags value from xml response , for it i use expression like this //count/text() but my count attribute is still empty , what should i change?
my xml reponse is something like this, AND I WANT TO GET THIS 72 AND WRITE IT IN MY COUNT ATTRIBUTE .
<SendMessage xmlns="http://www.talk.gov.uk/CM/envelope">
<EnvelopeVersion>2.0</EnvelopeVersion>
<Header>
<MessageDetails>
<Class></Class>
<Qualifier>response</Qualifier>
<Function>submit</Function>
<CorrelationID></CorrelationID>
<ResponseEndPoint/>
</MessageDetails>
<SenderDetails>
<IDAuthentication/>
<EmailAddress/>
</SenderDetails>
</Header>
<MessageDetails/>
<Body>
<Message xmlns="http://www.govtalk.gov.uk/CM/envelope">
<getEventDataResponse xmlns="http://www.talk.gov.uk/CM/envelope" xmlns:ns2="" xmlns:ns3="http://www.talk.gov.uk/CM/envelope" xmlns:ns4="http://www.talk.gov.uk/CM/envelope">
<count>72</count>
</Message>

you have namespace in your message xmlns="http://www.talk.gov.uk/CM/envelope"
it means that the name of count node is {http://www.talk.gov.uk/CM/envelope} count
the nifi processor EvaluateXPath 1.3.0 does not support namespaces however you can write your xpath like this to search for the element by local name:
//*[local-name()='count']/text()

Related

Spark SQL (Databricks) function xpath ignores empty tags in XML

Spark SQL (Databricks) function xpath ignores empty tags in XML. For example for below XML XPATH returns array ["ABC"]. We need it as ["ABC", NULL or empty string] because when we use this along with posexplode_outer, omitting null in XPATH will cause incorrect association.
Is there any option in XPATH to retain nulls? I did not find any detailed documentation for this.
SELECT xpath("<PARTY>
<PARTY_EVENT>
<EVENTTYPE>VISITED</EVENTTYPE>
<LOCATION>ABC</LOCATION>
</PARTY_EVENT>
<PARTY_EVENT>
<EVENTTYPE>VISITED</EVENTTYPE>
<LOCATION />
</PARTY_EVENT>
</PARTY>"
, '/PARTY/PARTY_EVENT/LOCATION/text()')
Add the nodes not containing any text by using [not(text())] selector:
(/PARTY/PARTY_EVENT/LOCATION|/PARTY/PARTY_EVENT/LOCATION[not(text())])/text()

JMeter Xpath2 extractor id's matching multiple conditions

Below is the sample XML fragment, from it i'm trying to filter out id's of articles matching both conditions as below. Currently i could extract id's for individual condition with help of expression below
get Avaialable articles, Xpath2 expression = (//*//*//*//*[starts-with(state,'Avaialable')])/id
get articles name starting with 'A' () , Xpath2 expression = (//*//*//*//*[starts-with(name,'A')])/id
I want to merge these conditions in a single expression and would like to
fetch id's of Articles where Name starts with 'A' AND articles which
are Available
. Tried multiple ways but not working as expected.
Dummy XML fragment:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns3:GetArtclesResponse
xmlns:ns2="XXX"
xmlns:ns4="XXX"
xmlns:ns3="XXX"
xmlns:ns6="XXX"
xmlns:ns5="XXX"
xmlns:ns8="XXX"
xmlns:ns7="XXX"
xmlns:ns13="XXX"
xmlns:ns9="XXX"
xmlns:ns12="XXX"
xmlns:ns11="XXX">
<serverTimeInfo timezone="+00:00" timestamp="1606409365419"/>
<items>
<count>2</count>
<articles>
<article>
<name>ABC</name>
<id>1234</id>
<state>Avaialable</state>
</article>
<article>
<name>XYZ</name>
<id>3456</id>
<state>Avaialable_Conditional</state>
</article>
</articles>
</items>
</ns3:GetArtclesResponse>
You can use and to check both:
(//*//*//*//*[starts-with(state,'Avaialable') and starts-with(name,'A')])/id
If you want to combine 2 different XPath expressions you can use | (union) operator like:
//article[state = 'Avaialable'] | //article[starts-with(name,'A')]
it will return you both:
nodes which have state=Available
and nodes which name starts with A
If you want to combine 2 conditions in a single XPath expression - go for and operator like:
//article[state = 'Avaialable' and starts-with(name,'A')]
it will return
nodes which nave state=available and whose name attribute starts with a
More information:
XPath Operators
The JMeter XPath2 Extractor: How to Achieve Better Correlations

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()

How to get parent element with attribute using xpath

I have posted sample XML and expected output kindly help to get the result.
Sample XML
<root>
<A id="1">
<B id="2"/>
<C id="2"/>
</A>
</root>
Expected output:
<A id="1"/>
You can formulate this query in several ways:
Find elements that have a matching attribute, only ascending all the time:
//*[#id=1]
Find the attribute, then ascend a step:
//#id[.=1]/..
Use the fn:id($id) function, given the document is validated and the ID-attribute is defined as such:
/id('1')
I think it's not possible what you're after. There's no way of selecting a node without its children using XPATH (meaning that it'd always return the nodes B and C in your case)
You could achieve this using XQuery, I'm not sure if this is what you want but here's an example where you create a new node based on an existing node that's stored in the $doc variable.
declare variable $doc := <root><A id="1"><B id="2"/><C id="2"/></A></root>;
element {fn:node-name($doc/*)} {$doc/*/#*}
The above returns <A id="1"></A>.
is that what you are looking for?
//*[#id='1']/parent::* , similar to //*[#id='1']/../
if you want to verify that parent is root :
//*[#id='1']/parent::root
https://en.wikipedia.org/wiki/XPath
if you need not just parent - but previous element with some attribute: Read about Axis specifiers and use Axis "ancestor::" =)

XPath Wildcard -- Any Node Name, Must have Specific Attribute Value

I am having difficulty figuring out an XPath query that would allow me to return nodes based on the value of the Program attribute in the example below. For example, I would like to be able to search all nodes for a value of the Program attribute = "011.pas". I tried /Items/*[Program="012.pas"] and also /Items/Item*[Program="01.pas"] but neither works. What is the correct expression?
<Items>
<Item0 Program="01.pas"></Item0>
<Item1 Program="011.pas"></Item1>
</Items>
The attribute is selected with #Program, the child elements of the Items element with /Items/*, so you want /Items/*[#Program = '011.pas'].
Try this :
/items/*[#Program='011.pas']

Resources