XSLT2: How to match a single node based on priority - xslt-2.0

I need to make a new xml structure where only one image-version exist, and that should be the version that is either "a", "16x9s" or "4x3s" - in that priority. So if an image version "a" exist, then only that image is chosen. if it doesn't then look for "16x9s" and finally "4x3s".
Also needed are a few other nodes(in caps in the wanted result code below), while all the other nodes should be discarded.
The xml (an excerpt, it can be a lot longer or shorter):
<?xml version="1.0" encoding="iso-8859-1"?>
<io>
<publication id="106125"/>
<related-images>
<image id="1112835">
<caption>null</caption>
<placement>FRONTPAGETITLE</placement>
<alignment>left</alignment>
<photographer></photographer>
<credit></credit>
<name>Some text</name>
<author></author>
<copyright></copyright>
<path>Image Root</path>
<description></description>
<alt-text></alt-text>
<image-version version-id="2060510" version-type="16x9s">
<url>/archive/01112/Thomas-Hicks-1_111283516x9s.jpg</url>
<width>649</width>
<height>365</height>
</image-version>
<image-version version-id="2060512" version-type="a">
<url>/archive/01112/Thomas-Hicks-16_11128353x4s.jpg</url>
<width>413</width>
<height>550</height>
</image-version>
<image-version version-id="2060513" version-type="4x3s">
<url>/archive/01112/Thomas-Hicks-16_11128354x3s.jpg</url>
<width>550</width>
<height>413</height>
</image-version>
</image>
<image id="1111482">
<caption>Some text</caption>
<placement>FRONTPAGELEADTEXT</placement>
<alignment>left</alignment>
<photographer></photographer>
<credit></credit>
<name>Some text</name>
<author></author>
<copyright></copyright>
<path>Image Root</path>
<description></description>
<alt-text></alt-text>
<image-version version-id="2060099" version-type="4x3s">
<url>/archive/01111/1904_tugofwar_11114824x3s.jpg</url>
<width>640</width>
<height>363</height>
</image-version>
<image-version version-id="2060075" version-type="f-tn">
<url>/archive/01111/1904_tugofwar_1111482f-tn.jpg</url>
<width>200</width>
<height>113</height>
</image-version>
<image-version version-id="2060094" version-type="y">
<url>/archive/01111/1904_tugofwar_1111482y.jpg</url>
<width>484</width>
<height>274</height>
</image-version>
</image>
<image id="1111465">
<caption>Some text</caption>
<placement>FRONTPAGELEADTEXT</placement>
<alignment>left</alignment>
<photographer>Getty Images</photographer>
<credit></credit>
<name>Some text</name>
<author></author>
<copyright></copyright>
<path>Image Root</path>
<description></description>
<alt-text></alt-text>
<image-version version-id="2058398" version-type="a">
<url>/archive/01111/1896_1111465a.jpg</url>
<width>1499</width>
<height>1103</height>
</image-version>
</image>
</related-images>
</io>
The wanted result:
<PTR:image>
<PTR:width>WIDTH OF IMAGE</PTR:width>
<PTR:height>HEIGHT OF IMAGE</PTR:height>
<PTR:src>IMAGE URL</PTR:src>
<PTR:title>
NAME
</PTR:title>
<PTR:description>
CAPTION
</PTR:description>
<PTR:author>
PHOTOGRAPHER
</PTR:author>
</PTR:image>
I've tried a few things, like xsl:when, but my skill level is not good enough yet to make it work. Any help would be greatly appreciated.
Cheers.

Like Dr. Kay suggested, create a sequence and use the first occurrence in that sequence.
Here is a complete example.
XML Input
<io>
<publication id="106125"/>
<related-images>
<image id="1112835">
<caption>null</caption>
<placement>FRONTPAGETITLE</placement>
<alignment>left</alignment>
<photographer></photographer>
<credit></credit>
<name>Some text</name>
<author></author>
<copyright></copyright>
<path>Image Root</path>
<description></description>
<alt-text></alt-text>
<image-version version-id="2060510" version-type="16x9s">
<url>/archive/01112/Thomas-Hicks-1_111283516x9s.jpg</url>
<width>649</width>
<height>365</height>
</image-version>
<image-version version-id="2060512" version-type="a">
<url>/archive/01112/Thomas-Hicks-16_11128353x4s.jpg</url>
<width>413</width>
<height>550</height>
</image-version>
<image-version version-id="2060513" version-type="4x3s">
<url>/archive/01112/Thomas-Hicks-16_11128354x3s.jpg</url>
<width>550</width>
<height>413</height>
</image-version>
</image>
<image id="1111482">
<caption>Some text</caption>
<placement>FRONTPAGELEADTEXT</placement>
<alignment>left</alignment>
<photographer></photographer>
<credit></credit>
<name>Some text</name>
<author></author>
<copyright></copyright>
<path>Image Root</path>
<description></description>
<alt-text></alt-text>
<image-version version-id="2060099" version-type="4x3s">
<url>/archive/01111/1904_tugofwar_11114824x3s.jpg</url>
<width>640</width>
<height>363</height>
</image-version>
<image-version version-id="2060075" version-type="f-tn">
<url>/archive/01111/1904_tugofwar_1111482f-tn.jpg</url>
<width>200</width>
<height>113</height>
</image-version>
<image-version version-id="2060094" version-type="y">
<url>/archive/01111/1904_tugofwar_1111482y.jpg</url>
<width>484</width>
<height>274</height>
</image-version>
</image>
<image id="1111465">
<caption>Some text</caption>
<placement>FRONTPAGELEADTEXT</placement>
<alignment>left</alignment>
<photographer>Getty Images</photographer>
<credit></credit>
<name>Some text</name>
<author></author>
<copyright></copyright>
<path>Image Root</path>
<description></description>
<alt-text></alt-text>
<image-version version-id="2058398" version-type="a">
<url>/archive/01111/1896_1111465a.jpg</url>
<width>1499</width>
<height>1103</height>
</image-version>
</image>
</related-images>
</io>
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:PTR="whatever the PTR namespace uri is">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="image">
<xsl:variable name="targetImage" select="
(image-version[#version-type='a'],
image-version[#version-type='16x9s'],
image-version[#version-type='4x3s'])[1]"/>
<PTR:image>
<xsl:apply-templates select="#*"/>
<PTR:width><xsl:value-of select="$targetImage/width"/></PTR:width>
<PTR:height><xsl:value-of select="$targetImage/height"/></PTR:height>
<PTR:src><xsl:value-of select="$targetImage/url"/></PTR:src>
<PTR:title><xsl:value-of select="name"/></PTR:title>
<PTR:description><xsl:value-of select="caption"/></PTR:description>
<PTR:author><xsl:value-of select="photographer"/></PTR:author>
</PTR:image>
</xsl:template>
</xsl:stylesheet>
XML Output
<io>
<publication id="106125"/>
<related-images>
<PTR:image xmlns:PTR="whatever the PTR namespace uri is" id="1112835">
<PTR:width>413</PTR:width>
<PTR:height>550</PTR:height>
<PTR:src>/archive/01112/Thomas-Hicks-16_11128353x4s.jpg</PTR:src>
<PTR:title>Some text</PTR:title>
<PTR:description>null</PTR:description>
<PTR:author/>
</PTR:image>
<PTR:image xmlns:PTR="whatever the PTR namespace uri is" id="1111482">
<PTR:width>640</PTR:width>
<PTR:height>363</PTR:height>
<PTR:src>/archive/01111/1904_tugofwar_11114824x3s.jpg</PTR:src>
<PTR:title>Some text</PTR:title>
<PTR:description>Some text</PTR:description>
<PTR:author/>
</PTR:image>
<PTR:image xmlns:PTR="whatever the PTR namespace uri is" id="1111465">
<PTR:width>1499</PTR:width>
<PTR:height>1103</PTR:height>
<PTR:src>/archive/01111/1896_1111465a.jpg</PTR:src>
<PTR:title>Some text</PTR:title>
<PTR:description>Some text</PTR:description>
<PTR:author>Getty Images</PTR:author>
</PTR:image>
</related-images>
</io>

So if an image version "a" exist, then only that image is chosen. if
it doesn't then look for "16x9s" and finally "4x3s".
That's
select="(image[#version-type='a'], image[#version-type='16x9s'],
image[#version-type='4x3s'])[1]"

Related

How to compare a single value to an array using XSLT

I want to compare a single value if it's existing to an array. I have an XML input file:
<wd:Report_Entry
xmlns:wd="urn:com.workday.report/CRI_-_INTSG031_CM_011_-_PUBBS_HSA_Customer_Invoice">
<wd:CFI_ARI_PUBBS_HSA_group>
<wd:pubbsType>1</wd:pubbsType>
<wd:pubbsService>A+</wd:pubbsService>
<wd:validFrom>2019-08-01</wd:validFrom>
<wd:validTo>2100-01-01</wd:validTo>
<wd:CF_FD_PUBBS_HSA_Valid_From_Date>2019-08-01</wd:CF_FD_PUBBS_HSA_Valid_From_Date>
<wd:CF_FD_PUBBS_HSA_Valid_To_Date>2100-01-01</wd:CF_FD_PUBBS_HSA_Valid_To_Date>
</wd:CFI_ARI_PUBBS_HSA_group>
<wd:CFI_ARI_PUBBS_HSA_group>
<wd:pubbsType>1</wd:pubbsType>
<wd:pubbsService>A-</wd:pubbsService>
<wd:validFrom>2019-08-01</wd:validFrom>
<wd:validTo>2100-01-01</wd:validTo>
<wd:CF_FD_PUBBS_HSA_Valid_From_Date>2019-08-01</wd:CF_FD_PUBBS_HSA_Valid_From_Date>
<wd:CF_FD_PUBBS_HSA_Valid_To_Date>2100-01-01</wd:CF_FD_PUBBS_HSA_Valid_To_Date>
</wd:CFI_ARI_PUBBS_HSA_group>
<wd:CFI_ARI_PUBBS_HSA_group>
<wd:pubbsType>FMDAUTOPSY</wd:pubbsType>
<wd:pubbsService>FMDAUTOPSY</wd:pubbsService>
<wd:validFrom>2020-02-02</wd:validFrom>
<wd:validTo>2020-02-01</wd:validTo>
<wd:CF_FD_PUBBS_HSA_Valid_From_Date>2020-02-01</wd:CF_FD_PUBBS_HSA_Valid_From_Date>
<wd:CF_FD_PUBBS_HSA_Valid_To_Date>2100-01-01</wd:CF_FD_PUBBS_HSA_Valid_To_Date>
</wd:CFI_ARI_PUBBS_HSA_group>
<wd:CFI_ARI_PUBBS_HSA_group>
<wd:pubbsType>FMDBODYSTOR</wd:pubbsType>
<wd:pubbsService>FMDBODYSTOR</wd:pubbsService>
<wd:validFrom>2020-01-01</wd:validFrom>
<wd:validTo>2020-01-31</wd:validTo>
<wd:CF_FD_PUBBS_HSA_Valid_From_Date>2020-01-01</wd:CF_FD_PUBBS_HSA_Valid_From_Date>
<wd:CF_FD_PUBBS_HSA_Valid_To_Date>2020-01-31</wd:CF_FD_PUBBS_HSA_Valid_To_Date>
</wd:CFI_ARI_PUBBS_HSA_group>
<wd:Customer_Invoice_Lines_group>
<wd:referenceID>CUSTOMER_INVOICE_LINE-6-46</wd:referenceID>
<wd:Unit_Cost>0</wd:Unit_Cost>
<wd:Quantity>0</wd:Quantity>
<wd:Calculated_Tax_Amount>0</wd:Calculated_Tax_Amount>
<wd:CFI_AC_Merchandise_Amount>100</wd:CFI_AC_Merchandise_Amount>
<wd:Line_Item_Description>LINE ITEM DESC</wd:Line_Item_Description>
<wd:Line_Memo>LINE MEMO</wd:Line_Memo>
<wd:Transaction_Tax_Amount>0</wd:Transaction_Tax_Amount>
<wd:CFI_LRV_Sales_Item_Reference_ID>FMDAUTOPSY</wd:CFI_LRV_Sales_Item_Reference_ID>
</wd:Customer_Invoice_Lines_group>
<wd:CFI_FD_PUBBS_HSA_Current_Date>2020-02-16</wd:CFI_FD_PUBBS_HSA_Current_Date>
</wd:Report_Entry>
I want to know if the wd:CFI_LRV_Sales_Item_Reference_ID value is equal to wd:Customer_Invoice_Lines_group/wd:CFI_ARI_PUBBS_HSA_group/wd:pubbsService and wd:CFI_FD_PUBBS_HSA_Current_Date is greater than wd:CF_FD_PUBBS_HSA_Valid_To_Date and then just return a string value true if there is. I have a code like this but this doesn't work because I'm comparing a value to an object that has multiple values. Not sure how to do compare single value to an array using xslt 2 or 3.. Appreciate the help.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mf="http://example.com/mf"
exclude-result-prefixes="#all" version="3.0"
xmlns:wd="urn:com.workday.report/CRI_-_INTSG031_CM_011_-_PUBBS_HSA_Customer_Invoice"
xmlns:d9="urn:this-stylesheet">
<xsl:output method="xml"/>
<xsl:template match="/">
<PUBBS>
<xsl:for-each select="wd:Report_Entry/wd:Customer_Invoice_Lines_group">
<xsl:if test="wd:CFI_LRV_Sales_Item_Reference_ID != ''">
<xsl:for-each select="../wd:CFI_ARI_PUBBS_HSA_group">
<xsl:if test="../wd:CFI_ARI_PUBBS_HSA_group/wd:pubbsService != ''
and wd:CFI_LRV_Sales_Item_Reference_ID = ../wd:CFI_ARI_PUBBS_HSA_group/wd:pubbsService
and xs:date(../wd:CFI_FD_PUBBS_HSA_Current_Date) > xs:date(../wd:CFI_ARI_PUBBS_HSA_group/wd:CF_FD_PUBBS_HSA_Valid_To_Date)
">
<HASINVALIDSALESITEM>
<xsl:value-of select="'true'"/>
</HASINVALIDSALESITEM>
</xsl:if>
</xsl:for-each>
</xsl:if>
</xsl:for-each>
</PUBBS>
</xsl:template>
</xsl:stylesheet>
I have tried to simplify the code by using xpath-default-namespace and by using templates; I have also assumed the two values you want to compare the two details of the various CFI_ARI_PUBBS_HSA_group to only exist once in the input document:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xpath-default-namespace="urn:com.workday.report/CRI_-_INTSG031_CM_011_-_PUBBS_HSA_Customer_Invoice"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output method="xml" indent="yes"/>
<xsl:mode on-no-match="shallow-skip"/>
<xsl:template match="/*">
<PUBBS>
<xsl:apply-templates select="CFI_ARI_PUBBS_HSA_group"/>
</PUBBS>
</xsl:template>
<xsl:template match="CFI_ARI_PUBBS_HSA_group[xs:date(//CFI_FD_PUBBS_HSA_Current_Date) > xs:date(CF_FD_PUBBS_HSA_Valid_To_Date)
and
//CFI_LRV_Sales_Item_Reference_ID = pubbsService]">
<HASINVALIDSALESITEM>true</HASINVALIDSALESITEM>
</xsl:template>
</xsl:stylesheet>
At https://xsltfiddle.liberty-development.net/jz1Q1ym that gives an empty <PUBBS/>, which seems the right result as the only CFI_ARI_PUBBS_HSA_group with pubbsService having the value FMDAUTOPSY has a CF_FD_PUBBS_HSA_Valid_To_Date of 2100-01-01 and the CFI_FD_PUBBS_HSA_Current_Date with the value 2020-02-16 is not greater than that.
It is not quite clear whether you want a single output of HASINVALIDSALESITEM even if there are several but the code could obviously adapted.

recursive call in nested xml fails

I want to recursively call on element vrijeInhoudGroep, but the node test in the choose clause is not performed. Instead, the second test on element vrijeInhoudElement is successful. Everything I have applied does not work. Can anyone give me a backing?
My xml input:
<?xml version="1.0"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://services" xmlns:v11="http://services11" xmlns:v12="http://services12">
<soapenv:Header/>
<soapenv:Body>
<v1:creeerDocumentRequest>
<v11:documentInhoud>
<v12:vrijeInhoudGroep type="FirstGroep">
<v12:vrijInhoudGroep type="GenesteGroep_1">
<v12:vrijeInhoudElement>
<v12:label>Label1</v12:label>
<v12:waarde>waard1</v12:waarde>
<v12:datatype>tekst1</v12:datatype>
</v12:vrijeInhoudElement>
<v12:vrijeInhoudElement>
<v12:label>Label2</v12:label>
<v12:waarde>waard2</v12:waarde>
<v12:datatype>tekst2</v12:datatype>
</v12:vrijeInhoudElement>
</v12:vrijInhoudGroep>
<v12:vrijInhoudGroep type="GenesteGroep_2">
<v12:vrijeInhoudElement>
<v12:label>Label3</v12:label>
<v12:waarde>waard3</v12:waarde>
<v12:datatype>tekst3</v12:datatype>
</v12:vrijeInhoudElement>
</v12:vrijInhoudGroep>
<v12:vrijeInhoudElement>
<v12:label>Label4</v12:label>
<v12:waarde>waard4</v12:waarde>
<v12:datatype>tekst4</v12:datatype>
</v12:vrijeInhoudElement>
<v12:vrijeInhoudElement>
<v12:label>Label5</v12:label>
<v12:waarde>waard5</v12:waarde>
<v12:datatype>tekst5</v12:datatype>
</v12:vrijeInhoudElement>
</v12:vrijeInhoudGroep>
</v11:documentInhoud>
</v1:creeerDocumentRequest>
</soapenv:Body>
</soapenv:Envelope>
My xml output:
<?xml version="1.0" encoding="UTF-8"?>
<vrijeInhoudGroep type="documentInhoud">
<vrijeInhoudGroep>v12:vrijeInhoudGroep</vrijeInhoudGroep>
<ELLEMENT/>
<mywrapper>
<v12:label xmlns:soapenv="http://s...">Label4</v12:label>
<v12:waarde xmlns:soapenv="http://s..." >waard4</v12:waarde>
<v12:datatype xmlns:soapenv="http://s..." >tekst4</v12:datatype>
</mywrapper>
<mywrapper>
<v12:label xmlns:soapenv="http://s...." >Label5</v12:label>
<v12:waarde xmlns:soapenv="http://s..." >waard5</v12:waarde>
<v12:datatype xmlns:soapenv="http://s...">tekst5</v12:datatype>
</mywrapper>
</vrijeInhoudGroep>
My xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:v11="http://services11" xmlns:v12="http://services12" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:v1="http://services"
version="2.0"
exclude-result-prefixes="v11 v12 v1 xsi xs">
<xsl:output method="xml" indent="no"/>
<xsl:template match="/">
<xsl:apply-templates select="//v1:creeerDocumentRequest"/>
</xsl:template>
<xsl:template match="v1:creeerDocumentRequest">
<vrijeInhoudGroep type="documentInhoud">
<xsl:apply-templates select="v11:documentInhoud"/>
</vrijeInhoudGroep>
</xsl:template>
<xsl:template match="v11:documentInhoud">
<xsl:apply-templates select="v12:vrijeInhoudGroep"/>
</xsl:template>
<xsl:template match="v12:vrijeInhoudGroep[#type]">
<vrijeInhoudGroep>
<xsl:value-of select="name()"/>
</vrijeInhoudGroep>
<xsl:choose>
<xsl:when test="v12:vrijeInhoudGroep">
<!-- HERE I TRY A RECURSIVE CALL, BUT THIS TEST DOES'T WORK -->
<xsl:apply-templates select="v12:vrijeInhoudGroep"/>
</xsl:when>
<xsl:when test="v12:vrijeInhoudElement">
<!-- INSTEAD IT COMES HERE TO PROCES THE vrijeInhoudElement -->
<ELLEMENT/>
<xsl:apply-templates select="v12:vrijeInhoudElement"/>
</xsl:when>
<xsl:otherwise><NOPE/></xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="v12:vrijeInhoudElement">
<mywrapper>
<xsl:copy-of select="node()"/>
</mywrapper>
</xsl:template>
</xsl:stylesheet>
Target xml should be something like this:
<...>
<vrijeInhoudGroep type="EerstGroep">
<vrijeInhoudGroep type="GenesteGroep_1">
<vrijeInhoudElement naam="Label1 format="tekst1">waard1</vrijeInhoudElement>
</vrijeInhoudGroep>
<vrijeInhoudGroep type="GenesteGroep_2">
<vrijeInhoudElement naam="Label2 format="tekst2">waard2</vrijeInhoudElement>
<vrijeInhoudElement naam="Label3 format="tekst3">waard3</vrijeInhoudElement>
</vrijeInhoudGroep>
<vrijeInhoudElement naam="Label3 format="tekst3">waard3</vrijeInhoudElement>
<vrijeInhoudElement naam="Label4 format="tekst4">waard4</vrijeInhoudElement>
</vrijeInhoudGroep>
</...>
What should I do to make this recursive call work properly?

SaxonApiException: The context item for axis step ./CLIENT is absent

I am trying to convert and XML to an XML using XSLT 2.0 in saxon/java. I am using a sample XML I found on stack overflow thread "Applying Muenchian grouping for a simple XML with XSLT"
However I am getting an error : XPDY0002: The context item for axis step ./CLIENT is absent.
My test XSL:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output omit-xml-declaration="no" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="CLIENTS" name="main">
<CLIENTS>
<xsl:for-each-group select="CLIENT" group-by="NAME">
<xsl:comment><xsl:value-of select="current-grouping-key()"/> </xsl:comment>
<CLIENT>
<xsl:sequence select="NAME" />
<xsl:for-each select="current-group()">
<ACCOUNT>
<xsl:sequence select="*[not(self::NAME)]" />
</ACCOUNT>
</xsl:for-each>
</CLIENT>
</xsl:for-each-group>
</CLIENTS>
</xsl:template>
</xsl:stylesheet>
My Test XML:
<CLIENTS>
<CLIENT>
<NAME>John</NAME>
<ACCOUNT_NUMBER>1424763562761</ACCOUNT_NUMBER>
<LAST_USED>2012-10-03</LAST_USED>
<AMOUNT>5000</AMOUNT>
</CLIENT>
<CLIENT>
<NAME>John</NAME>
<ACCOUNT_NUMBER>543667543732</ACCOUNT_NUMBER>
<LAST_USED>2012-10-02</LAST_USED>
<AMOUNT>10000</AMOUNT>
</CLIENT>
</CLIENTS>
My Java ( which works with other transforms) :
void xmlXSLTParser(){
String xslFile = commonPath + "/xslt/inputPointCSVTOXML_style2.xsl";
String inputFile = "file:///" + commonPath + pointWorkFile;
String outputFile = commonPath + pointWorkFile + ".final";
try {
Processor proc = new Processor(false);
XsltCompiler comp = proc.newXsltCompiler();
XsltExecutable exp = comp.compile(new StreamSource(new File(xslFile)));
Serializer out = new Serializer();
out.setOutputProperty(Serializer.Property.METHOD, "xml");
out.setOutputProperty(Serializer.Property.INDENT, "yes");
out.setOutputFile(new File(outputFile));
XsltTransformer trans = exp.load();
trans.setInitialTemplate(new QName("main"));
//trans.setParameter(new QName("url-of-csv"),new XdmAtomicValue(inputFile));
trans.setDestination(out);
trans.transform();
System.out.println("Output written to text file");
} catch (SaxonApiException e) {
println("XSLT Error :" + e );
}
}
}
My Error in detail:
Error at char 6 in xsl:for-each-group/#select on line 10 column 59 of inputPointCSVTOXML_style2.xsl:
XPDY0002: The context item for axis step ./CLIENT is absent
XSLT Error :net.sf.saxon.s9api.SaxonApiException: The context item for axis step ./CLIENT is absent
Your Java code does not set any context item, instead it sets an initial template. So you will need to make sure you provide the input XML as the context item to the XsltTransformer, using http://saxonica.com/html/documentation/javadoc/net/sf/saxon/s9api/XsltTransformer.html#setInitialContextNode(net.sf.saxon.s9api.XdmNode) or as a Source, using http://saxonica.com/html/documentation/javadoc/net/sf/saxon/s9api/XsltTransformer.html#setSource(javax.xml.transform.Source).
So instead of trans.setInitialTemplate(new QName("main")); use trans.setSource(new StreamSource(inputFile));.

Count the child Node

I have below payload ,where I have to count number of child elements under <Document>.
For example:
<Document>
<Class>D</Class>`enter code here`
<ClassDescription>Drawings</ClassDescription>
<ClientDocumentNumber>12345</ClientDocumentNumber>
<Document>
The count will be 3.
The Payload is as below. Check this code.
<?xml version="1.0" encoding="UTF-8"?>
<InputVariable>
<part name="payload">
<ProjectMessage>
<ConversationId>E53252F709653493E0401E0A13916A2E</ConversationId>
<SourceApplicationId>Convero</SourceApplicationId>
<Operation>INS DOC</Operation>
<ModifiedByUserEmail>daviD.Woo#xyz.com</ModifiedByUserEmail>
<Project>
<Id>100020</Id>
<DocumentList>
<Document>
<Class>D</Class>
<ClassDescription>Drawings</ClassDescription>
<ClientDocumentNumber>12345</ClientDocumentNumber>
<ClientRevisionNumber>2.0</ClientRevisionNumber>
<Discipline>141</Discipline>
<DisciplineDescription>ACN</DisciplineDescription>
<Facility>24</Facility>
<Number>100020-24-140-SKT-0002</Number>
<OSROriginator>086238</OSROriginator>
<Revision>2.0</Revision>
<RevisionDate>2013-02-11T00:00:00Z</RevisionDate>
<Status>A</Status>
<StatusDescription>Active</StatusDescription>
<SupplierDocumentNumber>523570.000</SupplierDocumentNumber>
<SupplierRevisionNumber>CCC</SupplierRevisionNumber>
<Title>Test for FileNet</Title>
<Type>NA</Type>
<TypeDescription>NA</TypeDescription>
</Document>
</DocumentList>
</Project>
</ProjectMessage>
</part>
</InputVariable>
<xsl:template match="Document">
<xsl:value-of select="count(*)"/>
</xsl:template>
is a template matching Document elements and counting the child elements.

Nokogiri get xpath from Nokogiri::XML::Element

How to get xpath for rc an element returned by search
f=File.open('/media/cc.xml')
doc = Nokogiri::XML f
rc = doc.search('realmCode')
[#<Nokogiri::XML::Element:0x15a4d714 name="realmCode" namespace=#<Nokogiri::XML::Namespace:0x15a4dafc href="urn:hl7-org:v3"> attributes=[#<Nokogiri::XML::Attr:0x15a4d5c0 name="code" value="US">]>]
Is there a way to extract xpath from rc ?
updated with xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/ccda.xsl"?>
<ClinicalDocument xmlns:sdtc="urn:hl7-org:sdtc" xmlns:vocdo="urn:hl7-org:v3/voc" xmlns="urn:hl7-org:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mif="urn:hl7-org:v3/mif">
<realmCode code="US"/>
<typeId root="2.16.840.1.113883.1.3" extension="POCD_HD000040"/>
<templateId root="2.16.840.1.113883.10.20.22.1.1"/>
<templateId root="2.16.840.1.113883.10.20.22.1.2"/>
<id root="2.16.840.1.113883.19.5.99999.1" extension="Test CCDA"/>
<code codeSystem="2.16.840.1.113883.6.1" codeSystemName="LOINC" code="34133-9" displayName="Summarization of Episode Note"/>
<title>Continuity of Care Document (C-CDA)</title>
<effectiveTime value="20130809043133+0000"/>
<confidentialityCode codeSystem="2.16.840.1.113883.5.25" codeSystemName="HL7 Confidentiality" code="N" displayName="Normal"/>
<languageCode code="en-US"/>
<recordTarget>
<patientRole>
<id root="2.16.840.1.113883.4.6" extension="1"/>
<id root="2.16.840.1.113883.4.1" extension="123-101-5230"/>
<addr use="HP">
<streetAddressLine>1357 Amber Drive</streetAddressLine>
<city nullFlavor="UNK"/>
<state nullFlavor="UNK"/>
<postalCode>97006</postalCode>
<country nullFlavor="UNK"/>
</addr>
<telecom value="3545345" use="HP"/>
<patient>
<name use="L">
<given qualifier="BR">test</given>
<family qualifier="CL">overall</family>
<prefix qualifier="IN">Mr</prefix>
</name>
<administrativeGenderCode codeSystem="2.16.840.1.113883.5.1" codeSystemName="HL7 AdministrativeGender" code="M" displayName="Male"/>
<birthTime value="19770429"/>
<raceCode codeSystem="2.16.840.1.113883.6.238" codeSystemName="Race and Ethnicity - CDC" code="2028-9" displayName="Asian"/>
<ethnicGroupCode codeSystem="2.16.840.1.113883.6.238" codeSystemName="Race and Ethnicity - CDC" code="2135-2" displayName="Hispanic or Latino"/>
<languageCommunication>
<languageCode code="eng"/>
<preferenceInd value="true"/>
</languageCommunication>
</patient>
</patientRole>
</recordTarget>
</ClinicalDocument>
rc is not an element-it's an array of matching elements:
results = rc.map do |node|
Nokogiri::CSS.xpath_for node.css_path
end
p results
Or, if you know there is only one matching element:
xpath = Nokogiri::CSS.xpath_for rc[0].css_path
Note that xpath_for returns an array, so you will need to extract the first element of the array:
xpath.first

Resources