getting first node of xml in logicapps - xpath

I need to have first node of below xml that is inside of FIToFICstmrCdtTrf. However, xpath returns binary data.
xpath(xml(triggerBody()),'/')
xpath(xml(triggerBody())x,'/FIToFICstmrCdtTrf')
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02">
<FIToFICstmrCdtTrf>
<GrpHdr>
<MsgId>x</MsgId>
<CreDtTm>x</CreDtTm>
<NbOfTxs>2</NbOfTxs>
....

Your XML is bound to the namespace urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02, so unless you register the namespace in order to be able to use a namespace-prefix in your XPath, you need to address the elements by their local-name().
For instance: /*[local-name()="Document"]/*[local-name()="FIToFICstmrCdtTrf"]
and then to select the first child element (GrpHdr), you can append a generic expression selecting any element * and apply a predicate filter to select the first: /*[1]
Putting it all together:
xpath(xml(triggerBody()),
'/*[local-name()="Document"]/*[local-name()="FIToFICstmrCdtTrf"]/*[1]')

After reproducing from my end, I was able to get this working by applying the below expressions in the flow of my logic app:
xpath(xml(variables('XML')),'/*[local-name()="Document"]/*[local-name()="FIToFICstmrCdtTrf"]/*')?[0]
OR
xpath(xml(variables('XML')),'/*[name()="Document"]/*[name()="FIToFICstmrCdtTrf"]/*')?[0]
Below is the flow of my logic app
RESULTS:

Related

Replace element by XPath

I try to replace some element of my input XML in Citrus Framework.
My Spring context contains:
<citrus:namespace-context>
<citrus:namespace prefix="def" uri="http://sample.com/xmlns/2005"/>
</citrus:namespace-context>
My input file starts with:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header>
<ns0:canonicalMessageHeader xmlns:ns0="http://sample.com/xmlns/2005">
<ns0:headerVersion>1.0</ns0:headerVersion>
<ns0:bodyVersion>1.0</ns0:bodyVersion>
<ns0:trackingInfo>
<ns0:eventHandlerInitInfo>
<ns0:processInfo>
<ns0:adapterTrackingId>214F27DF-E1FB-4E84-9122-390C5876ABD2:1</ns0:adapterTrackingId>
...
My endpoint is configured in that way:
<send endpoint="jms:topic:Order.Request?timeout=10000&connectionFactory=DEVconnectionFactoryFrom">
<message>
<resource file="com/sample/citrus/messages/input/SalesOrderTo.xml"/>
<element value="${track}" path="SOAP-ENV:Envelope/SOAP-ENV:Header/def:canonicalMessageHeader/def:trackingInfo/def:eventHandlerInitInfo/def:processInfo/def:adapterTrackingId"/>
I have the following error:
Can not evaluate xpath expression 'SOAP-ENV:Envelope/SOAP-ENV:Header/def:canonicalMessageHeader/def:trackingInfo/def:eventHandlerInitInfo/def:processInfo/def:adapterTrackingId'
at com/sample/citrus/SalesOrderToIT(sequential:45)
at com/sample/citrus/SalesOrderToIT(send:48-82)
Caused by: javax.xml.xpath.XPathExpressionException: org.apache.xpath.domapi.XPathStylesheetDOM3Exception: Prefix must resolve to a namespace: def
What's the possible cause of this error?
Best Regards
Global namespace declaration support is missing in Citrus when overwriting message elements in a send operation via XPath. This issue has been tracked: https://github.com/christophd/citrus/issues/331
In the meantime you have to use the exact same namespace prefix as in the message template file - in your case ns0:
Also you could throw away XPath overwrite and use the dot notated Node overwrite like this:
<send endpoint="jms:topic:Order.Request?timeout=10000&connectionFactory=DEVconnectionFactoryFrom">
<message>
<resource file="com/sample/citrus/messages/input/SalesOrderTo.xml"/>
<element value="${track}" path="Envelope.Header.canonicalMessageHeader.trackingInfo.eventHandlerInitInfo.processInfo.adapterTrackingId"/>
</message>
</send>
The dot notation is not based on namespaces but uses the local element names for finding the element in the message template. Obviously not as powerful as XPath but it works with current version of the framework.
You defined nso as namespace prefix in XML but then use def on the XPath, should be nso.

XSL - Externalizing Xpath queries to a property file

I went through various posts, regarding reading properties from external property files. Looks like there is a function - getProperty, which can read values from a property file, using a key. I am using saxon parser with spring integration. I am trying something like this, as described in the post :-
spring context file:
<int-xml:xslt-transformer id="xsltTransformer" input-channel="bulkStringInboundChannel"
output-channel="toBridgeChannel" result-type="StringResult" **transformer-factory-class="net.sf.saxon.TransformerFactoryImpl"**
xsl-resource="classpath:/META-INF/spring/integration/intake/intake-flow/bulkTransformer.xsl" />
XSL style sheet:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
....
<xsl:variable name="props" select="document('prop.xml')" />
<xsl:value-of select="f:getProperty('query1')"/>
....
Prop.xml:
query1 = /Batch/RequestID/text()
Error description:
XPST0003: XPath syntax error at char 23 on line 30 in {f:getProperty('query1')}:
XTSE0650: No template exists named getProperty
I now have two questions- first of all, how do I get rid of these errors?
Second, can I store xPath queries in property files? The post describes a method, to read a property file and use the value pertaining to its key. However, I am thinking that getProperty will just print the query's text equivalent instead of evaluating the query and processing it. Is there a way to achieve this?
Post - How to read a .properties file inside a .xsl file?
I can't help you with the Spring side of the question, but as for the Saxon side, you can call the JDK method System.getProperty() using code like this:
<xsl:value-of select="System:getProperty('user.dir')" xmlns:System="java:java.lang.System"/>
Java extensibility requires Saxon-PE or higher.
If the value of the property that you read is an XPath expression, you can then execute it using the XSLT 3.0 xsl:evaluate instruction - which also requires Saxon-PE or higher.

Correct Xpath -

I have a xml like -
<?xml version="1.0" encoding="UTF-8"?>
<oslc_cm:Collection xmlns:oslc_cm="http://open-services.net/xmlns/cm/1.0/"
oslc_cm:totalCount="7"
xmlns:dc="http://purl.org/dc/terms/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rtc_cm="http://jazz.net/xmlns/prod/jazz/rtc/cm/1.0/">
<rtc_cm:Action rdf:resource="https://rtc.gsissc.myatos.net:9443/ccm/oslc/workflows/_ezLt4PJ7EeGRg6GNKwqw9g/actions/com.ibm.team.workitem.defectWorkflow/com.ibm.team.workitem.defectWorkflow.action.resolve">
<dc:identifier>com.ibm.team.workitem.defectWorkflow.action.resolve</dc:identifier>
<rtc_cm:resultState rdf:resource="https://rtc.gsissc.myatos.net:9443/ccm/oslc/workflows/_ezLt4PJ7EeGRg6GNKwqw9g/states/com.ibm.team.workitem.defectWorkflow/3"/>
<dc:title>Resolve</dc:title>
<rtc_cm:iconUrl>https://rtc.gsissc.myatos.net:9443/ccm/service/com.ibm.team.workitem.common.internal.model.IImageContentService/processattachment/_ezLt4PJ7EeGRg6GNKwqw9g/workflow/resolve.gif</rtc_cm:iconUrl>
</rtc_cm:Action>
From it I have to fetch rtc_cm:resultState rdf:resource.
What would be the correct XPath for it. I am using XPathExpression xPathExpressionDescription = xpath.compile("../rtc_cm:resultState/#rdf:resource"); which is giving me null pointer.
Please guide me .
../rtc_cm:resultState/#rdf:resource
That's assuming the context node – the node to which your XPath expression is relative – is a sibling of rtc_cm:resultState.
You might be better with an absolute path, based on the document root. Something like:
/oslc_cm:Collection/rtc_cm:Action/rtc_cm:resultState/#rdf:resource
(and, of course, assuming you are passing an implementation of IXmlNamespaceResolver set up with all the applicable namespaces).
The absolute path would be:
/oslc_cm:Collection/rtc_cm:Action/rtc_cm:resultState/#rdf:resource
If you know there is only one instance of resultState or if you want to query for all instances:
//rtc_cm:resultState/#rdf:resource
Please make sure that your namespace manager has definitions for the namespaces you use in your XPath expression.

simplexml_load_file with xPath returns empty array

Getting XML from this URL:
$xml = simplexml_load_file('http://geocode-maps.yandex.ru/1.x/?geocode=37.71677,55.75208&kind=metro&spn=1,1&rspn=1');
print_r($xml) shows that XML loaded, but xpath always returns empty array. I tried:
$xml->xpath('/');
$xml->xpath('/ymaps');
$xml->xpath('/GeoObjectCollection');
$xml->xpath('/ymaps/GeoObjectCollection');
$xml->xpath('//GeoObjectCollection');
$xml->xpath('precision');
Why I got empty array? Hope I just missing something easy.
It might be rather easy, but I guess it is also the most common mistake in the history of XML: You are forgetting namespaces!
A lot of elements in the given XML are changing the default namespace and you have to consider that in your XPath.
You can first register your namespace like so:
$xml->registerXPathNamespace('y', 'http://maps.yandex.ru/ymaps/1.x');
$xml->registerXPathNamespace('a', 'http://maps.yandex.ru/attribution/1.x');
and then you can query your data:
$xml->xpath('//y:ymaps/y:GeoObjectCollection');

How to access jcr:root with XPath JCR Query

I would like to apply some java function on CQ5 dialogs. In the first step I search for dialog xml files in myComponent folder as follow:
NodeIterator tabRequiredFields = getQueryResult("/jcr:root/apps/myProject/pages/myComponent/dialog/jcr:root")
But this Query does not supply any results. crx Xpath tool does not show any result too see the follwoing picture:
my /jcr:root/apps/myProject/pages/myComponent/dialog.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="cq:Dialog"
stateful="false"
title="Test"
.....>
<items
jcr:primaryType="cq:Widget"
xtype="panel">
...
......
</items>
.....
</jcr:root>
I can access items as follow
NodeIterator tabRequiredFields = getQueryResult("/jcr:root/apps/myProject/pages/myComponent/dialog/items")
This works fine. My Question is: why for jcr:root? how to check, if jcr:root exists?
XML element named jcr:root from the dialog.xml doesn't create jcr:root node in the repository. It's a special, reserved identifier and CRX Package Manager puts all properties and subnodes of this element into a node which name is the same as name of the file without extension (in your case it'll be dialog).
If it's not clear, use CRX DE, open /apps/myProject/pages/myComponent and see what you can find there. That's why you should add /dialog rather than /jcr:root to the end of your path.
If you want to find all dialogs, use the primary type cq:Dialog, as rakhi4110 suggests. Following query:
/jcr:root/apps/myProject/pages//element(*, cq:Dialog)
will return all dialogs from /apps/myProject/pages (and descendants).

Resources