XPath as a string variable / property - xpath

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

Related

Xquery the function parse-xml() produces an error on &?

As XML content in an HTTP POST request, I receive the following which I process in Xquery 3.1 (eXist-db 5.2):
<request id="foo">
<p>The is a description with a line break<br/>and another linebreak<br/>and
here is an ampersand&.</p>
<request>
My objective is to take the node <p> and insert it into a TEI file in eXist-db. If I just insert the fragment as-is, no errors are thrown.
However I need to transform any instances of string <br/> into element <lb/> before adding it to the TEI document. I try that with fn:parse-xml.
Applying the following, however, throws an error on &amp...which surprises me:
let $xml := <request id="foo">
<p>The is a description with a line break<br/>and
another linebreak<br/>and here is an ampersand&.</p>
<request>
let $newxml := <p>{replace($xml//p/text(),"<br/>","<lb/>")}</p>
return <p>{fn:parse-xml($newxml)}</p>
error:
Description: err:FODC0006 String passed to fn:parse-xml is not a well-formed XML document.: Document is not valid.
Fatal : The entity name must immediately follow the '&' in the entity reference.
If I remove & the fragment parses just fine. Why is this producing an error if it is legal XML? How can I achieve the needed result?
Many thanks in advance.
ps. I am open to both Xquery and XSLT solutions.
It seems that the issue is the HTML entities. It would work with numeric entities (i.e. < instead of < and > instead of >), but the XML parser doesn't know about HTML character entities.
Useutil:parse-html() instead of fn:parse-xml().
let $xml := <request id="foo">
<p>The is a description with a line break<br/>and
another linebreak<br/>and here is an ampersand&.</p>
</request>
return <p>{util:parse-html($xml/p/text())/HTML/BODY/node()}</p>

how to get node value by EvaluateXpath processor?

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

Freemarker : Expression inside Expression

Is there any way that i can use an expression inside expression in Freemarker?
Example:
XML FIle
<Document>
<Row>
<item_date>01/01/2015</item_date>
</Row>
<Row>
<item_date>02/01/2015</item_date>
</Row>
</Document>
<#list 0..1 as i>
${Document.Row[${i}].item_date}
</#list>
I want to print as below
01/01/2015
02/01/2015
Any idea?
Thanks in Advance
Like this:
${Document.Row[i].item_date}
Note that if you are using an up-to-date version, you get this error message, which explains why:
You can't use "${" here as you are already in
FreeMarker-expression-mode. Thus, instead of ${myExpression}, just
write myExpression. (${...} is only needed where otherwise static text
is expected, i.e, outside FreeMarker tags and ${...}-s.)

Extract a value from a property in camel-context.xml

The input looks like below,
<book author="ABC" type="Children">
<id>123</id>
<name>XYZ</name>
</book>
I have set the above in property in an xml route as:
<camel:setProperty propertyName="REQUEST">
<camel:xpath>/node()</camel:xpath>
</camel:setProperty>
Then I do some other processing and based on the new response I want to extract the value of an author(i.e. ABC) from this Property and compare it with a element's text string from the response.
I tried a few ways using camel:xpath and camel:simple but am not able to extract the value from property.
What is the correct way to extract this property?
To access the REQUEST property using simple you can do this:
${property.REQUEST}
To access properties using xpath:
<camel:xpath>
function:properties("REQUEST")/[add your xpath expression here]
</camel:xpath>
More info on the properties function can be found here - https://camel.apache.org/xpath.html
I don't know if it's possible using properties, but you should be able to do it with headers.
Firstly:
<setHeader headerName="REQUEST">
<xpath>/node()</xpath>
</setHeader>
Then if you wanted to set another header with just the author value:
<setHeader headerName="REQUEST2">
<xpath headerName="REQUEST" resultType="java.lang.String">/book/#author</xpath>
</setHeader>
Or if you wanted to evaluate the value as a <choice> condition:
<when>
<xpath headerName="REQUEST">/book/#author = 'ABC'</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.

Resources