Scriptella: How to handle the error while fetching data from XML through Xpath - 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>

Related

Update parameter value in XML format

I have parameters stored in an XML file. Below is a sample of the file.
<?xml version="1.0" encoding="UTF-8"?>
<root>
<terminal id="A">
<terminalCapacity>3</terminalCapacity>
<terminalMembers id="1">
<memberID>0001</memberID>
<memberCapacity>2</memberCapacity>
</terminalMembers>
</terminal>
<terminal id="B">
<terminalCapacity>4</terminalCapacity>
<terminalMembers id="1">
<memberID>0002</memberID>
<memberCapacity>1</memberCapacity>
</terminalMembers>
<terminalMembers id="2">
<memberID>0003</memberID>
<memberCapacity>3</memberCapacity>
</terminalMembers>
</terminal>
</root>
Each terminalID is associated to a type of simpleModule found in my NED file. The idea is to programmatically update these values throughout the simulation run. The current logic revolves around getting the current parameters in XML format and update the memberCapacity field.
From the Omnet cPar and cXMLElement documentation, I tried using the par("moduleParameter").xmlValue()->getXML() function, but this returns the XML as a string. I also tried using the getAttribute() function, but to no success.
Don't do this. par("moduleParameter").xmlValue() will give you the in memory object tree of the XML document, but that is not meant for modification. Your XML file seems to be just a hierarchical structure and modules and their parameters can mirror that exactly. There is absolutely no reason to reinvent the wheel when you can mirror that with INI file parameters.

How to extract values (list and unique tags) from xml in Nifi?

I have a xml file that contains some tags, one is unique other are same tags. I'd like to get values from these tags and convert them to another xml tag. Here is example of xml file:
<?xml version="1.0" encoding="UTF-8"?>
<entry dataset="Swiss-Prot" created="2005-04-26" modified="2019-11-13" version="158" xmlns="http://uniprot.org/uniprot" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<accession>Q96IY4</accession>
<accession>A8K464</accession>
<accession>Q15114</accession>
<accession>Q5T9K1</accession>
<accession>Q5T9K2</accession>
<accession>Q9P2Y6</accession>
<name>CBPB2_HUMAN</name>
<protein>
<recommendedName>
<fullName>Carboxypeptidase B2</fullName>
<ecNumber evidence="7">3.4.17.20</ecNumber>
</recommendedName>
<alternativeName>
<fullName>Carboxypeptidase U</fullName>
<shortName>CPU</shortName>
</alternativeName>
<alternativeName>
<fullName>Plasma carboxypeptidase B</fullName>
<shortName>pCPB</shortName>
</alternativeName>
<alternativeName>
<fullName>Thrombin-activable fibrinolysis inhibitor</fullName>
<shortName>TAFI</shortName>
</alternativeName>
</protein>...other tags
</entry>
I though of using EvaluateXQuery processor and EvaluateXPath. EvaluateXQuery is using for getting accession and alternativeName tags. EvaluateXPath is using for getting name, recommendedName (fullName) tags.
Is it possible to use both and combine them to only xml or hust necessary to use EvaluateXQuery processor, like this:
<accessions>Q96IY4, A8K464, Q15114,...</accessions>
<name>CBPB2_HUMAN</name>
<recommendedName>Carboxypeptidase B2</recommendedName>
<alternativeNames>Carboxypeptidase U-CPU, Plasma carboxypeptidase B-pCPB,...</alternativeNames>
Can you help me, please?
Thank you!
Hi you may use processor execute groovy script and parse xml with a script to get your values and put them into attributes.

XSLTForms sort instance

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

camel:when on header value using blueprint

I have camel routes that make rest calls based on header values.
I had been using xpath to read values from xml and set them as the header and used xpath in a block as so:
<camel:setHeader headerName="clear">
<xpath>/TicketInfo/TicketData/Clear/text()</xpath>
</camel:setHeader>
<camel:choice>
<camel:when>
<camel:xpath>$clear='CLEARED'</camel:xpath>
<camel:doTry>
...
but now I am forced to use json so xpath will not work. I now have:
<camel:setHeader headerName="clear">
<camel:jsonpath>$.ticket.Type</camel:jsonpath>
</camel:setHeader>
<camel:choice>
<camel:when>
<camel:xpath>$clear='CLEARED'</camel:xpath>
<camel:doTry>
...
but obviously the <camel:xpath>$clear='CLEARED'</camel:xpath> part won't work anymore. Is there another way I can check the value of $clear header to restrict when the <camel:doTry> and following execute?
Try the simple language :
<camel:when>
<camel:simple>${in.header.clear} == 'CLEARED'</camel:simple>
<camel:doTry>
See this documentation

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.

Resources