XSLTForms sort instance - sorting

I'm using XSLTforms on exist-db server and I'm trying to sort the instance. Here is an example of the model:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xf="http://www.w3.org/2002/xforms">
<head>
<xf:model>
<xf:instance xmlns="" id="default">
<data>
<x>
<a>B</a>
<a>C</a>
<a>A</a>
</x>
</data>
</xf:instance>
</xf:model>
</head>
Is it possible to sort somehow the elements in xf:repeat in order to get such a result:
A
B
C
I've tried using this examples, but unfortunately they don't work when I copy them in my project:
https://github.com/AlainCouthures/xsltforms/blob/master/testsuite/xforms-examples/03-output/sorting/sort.xhtml
https://github.com/AlainCouthures/xsltforms/blob/master/testsuite/xforms-examples/13-javascript/xslt-sort.xhtml
I'm new to xforms and I can't figure out why these examples don't work, so I would be very grateful if someone could give me a working example or point me to the right way to sort data in xsltforms.
Thank you in advance!

Unfortunately, there is nothing about sorting data in XForms specifications and these examples, using XSLT as a workaround, are actually not fully supported by XSLTForms at the JSON API level.
To run this with XSLTForms, you should replace:
instanceElement.parentNode.rebuild();
instanceElement.parentNode.recalculate();
instanceElement.parentNode.revalidate();
instanceElement.parentNode.refresh();
by:
XsltForms_globals.addChange(instanceElement.parentNode.id);
XsltForms_xmlevents.dispatch(instanceElement.parentNode, "xforms-rebuild");
XsltForms_globals.refresh();

Related

getting first node of xml in logicapps

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:

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.

XPath format required on namespace node

Can someone please show me the XPath format i should use to retrieve the 2nd txnDetail node's billAmount ?
I am expecting value 10.00 but i have issues with the namespace and "a:" and XPath fails to retrieve the correct value.
<TransactionRsp xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<avlBal>818.00</avlBal>
<blkAmt>0.00</blkAmt>
<cardID>2561683577196298</cardID>
<currBill>GBP</currBill>
<endBal>390.00</endBal>
<logDateTime>2013-04-30T12:17:20.4249292Z</logDateTime>
<msgID>121719721</msgID>
<rspCode>000</rspCode>
<startBal>400.00</startBal>
<txnDetail xmlns:a="http://schemas.datacontract.org/2004/07/CoreModels">
<a:txnDetail>
<a:billAmount>400.00</a:billAmount>
<a:billConvRate>0.00</a:billConvRate>
<a:blkAmount>0.00</a:blkAmount>
<a:debOrCred>1</a:debOrCred>
<a:itemID>2278</a:itemID>
<a:itemType>6</a:itemType>
<a:txnAmount>0.00</a:txnAmount>
<a:txnCurrency/>
<a:txnDateTime>2012-02-23T14:35:45</a:txnDateTime>
<a:txnDescription></a:txnDescription>
</a:txnDetail>
<a:txnDetail>
<a:billAmount>10.00</a:billAmount>
<a:billConvRate>0.00</a:billConvRate>
<a:blkAmount>0.00</a:blkAmount>
<a:debOrCred>0</a:debOrCred>
<a:itemID>3058</a:itemID>
<a:itemType>5</a:itemType>
<a:txnAmount>0.00</a:txnAmount>
<a:txnCurrency/>
<a:txnDateTime>2012-07-30T12:22:14</a:txnDateTime>
<a:txnDescription>Fee: Card Issue</a:txnDescription>
</a:txnDetail>
</txnDetail>
</TransactionRsp>
It's:
//TransactionRsp/txnDetail/a:txnDetail[2]
However, depending on your programming language you might have to register the a namespace. The document might have a default namespace as well. (Don't expect that the xml you've posted is the whole document)
I have managed to pull the relevant data using the following XPath:
/TransactionRsp/txnDetail/[local-name()='txnDetail'][2]/[local-name()='billAmount']
Now I need to know how to filter out only txnDetail with an itemType = 6 ??
Any thoughts ?

Scriptella: How to handle the error while fetching data from XML through Xpath

i have one query regarding data fetching from XML xpath.
<query connection-id="in">
CommunicationCenter/Response/MenuData/Menu/Noun
<!--something I have to do inside script using the data fetched from xpath-->
</query>
My question is - suppose 1 of the XML doesn't have this structure of Xpath. It has "OtherCommCenter/MenuData/Menu/Noun" or something else structure. Then, when I run the job, it says the job is executed with no exception & as it does not get any value from xpath, nothing is happened. Means it gives back null. So, how do I catch the error there? I have to know which element in xpath creates the problem or if that is not possible, at least which xml is creating this error in structure ?
(because in my project, there are multiple XMLs I have to handle & I am doing that by submitting jobs to ExecutorService like you described in How to ETL multiple files using Scriptella?)
P.S. for the last part, I am doing like this
<connection id="in" driver="xpath" url="$input"/>
where "input" is the map key for the different xml file name.
can anybody help me? it is necessary to know asap for my project.
Here is an artificial example. Let's say there are kind of XMLs - people and cars.
people.xml:
<people>
<person></person>
</people>
Cars.xml:
<cars>
<car/>
</car>
The following xml runs 2 queries for /people/person and /cars/car and set global flags if at least one record was found:
<etl>
<connection driver="jexl" id="jexl"/>
<connection driver="xpath" id="xpath" url="input.xml"/>
<connection id="log" driver="text"/>
<query connection-id="xpath">
/people/person
<script connection-id="jexl">
# set flag to true if at least one element was found
etl.globals['people']=true;
</script>
</query>
<script connection-id="log" if="!etl.globals['people']">
WARNING: No people found in the XML file
</script>
<query connection-id="xpath">
/cars/car
<script connection-id="jexl">
etl.globals['cars']=true;
</script>
</query>
<script connection-id="log" if="!etl.globals['cars']">
WARNING: No cars found in the XML file
</script>
</etl>

How to Use Query_Match for Soap UI

I am having trouble using the MockOperation Editor in Soap UI.
I have got this request:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<methodName xmlns="http://tempuri.org/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<dataAreaId>error</dataAreaId>
<pInvoiceList>
<dataAreaId>NOTTHESAME</dataAreaId>
...
</pInvoiceList>
</methodName>
</s:Body>
</s:Envelope>
I tried almost every XPATH expression but I always get "Missing match in request"
What to fill in the Xpath box?
I tried:
//dataAreaId/text()
//dataAreaId/
//dataAreaId
/dataAreaId/text()
/dataAreaId
/methodName/dataAreaId/text()
/methodName/dataAreaId/
/methodName/dataAreaId
I finally managed to get it based on the answer from user1740631
Seems I it had to do with namespaces afterall.
The correct syntax:
declare namespace tem='http://tempuri.org/';
//tem:methodName/tem:dataAreaId[1]
If you don't care about namespaces you can use the following syntax:
XPath1.0
//*[local-name() = 'methodName']/*[local-name() = 'dataAreaId'][1]
XPath2.0
//*:methodName/*:dataAreaId[1]
Write like this
For First One
//methodName[1]/dataAreaId[1]
For Second one
//methodName[1]/pInvoiceList[1]/dataAreaId[1]
*If you have multiple node with same name in Xml then you should use numbers to locate that particular node.
There is a good hint: When defining an Assertion for a Testcase (or maybe also in the Mock-Window) there is a button "Declare" above the XPath-Expression-Field. It doesn't really look like a button, until you point with the mouse-pointer at it, so I didn't realize it at first.
Just click on the button an SoapUI (actually I use 5.2.1) will add the declare-statements for you, that you can use.
I found that feature coincidentally, as it is not really visible. Maybe this can help also...

Resources