XSLT 2, Mutiple grouping by attributes and elements - xslt-2.0

I can't seem to manage grouping couple based on their MaritalStatus.
I've manage to group all the person that are in a relationship ('DeFacto', 'Married') but can't figuring out how to group them in different households.
Basically if two persons make a couple they will create a Household. The household name will belong to the first person surname in the household, the NumberOfAdults will be hardcoded to '2' and the NumberOfDependants will be summed.
The couple is linked based on the Party.Identifier and the Party.MaritalStatus.RelatedEntityRef
What i have(simplified):
<PartySegment>
<Party Type="Guarantor" PrimaryApplicant="No">
<Identifier>b8b0f908b08e</Identifier>
<Person Sex="Female" FirstHomeBuyer="No" CustomerOfLender="No">
<PersonName>
<NameTitle Value="Lady"/>
<FirstName>Clemansa</FirstName>
<Surname>Sanchez</Surname>
</PersonName>
<MaritalStatus Status="DeFacto">
<RelatedEntityRef>ea384b0bf3f5</RelatedEntityRef>
</MaritalStatus>
<NumberOfDependents>1</NumberOfDependents>
</Person>
</Party>
<Party Type="Applicant" PrimaryApplicant="Yes" ExistingCustomerID="1231">
<Identifier>bd8c65a3ad80</Identifier>
<Person Sex="Female" FirstHomeBuyer="Yes" CustomerOfLender="Yes">
<PersonName>
<NameTitle Value="Mrs"/>
<FirstName>Cheryl</FirstName>
<Surname>Bonkers</Surname>
</PersonName>
<MaritalStatus Status="Married">
<RelatedEntityRef>ee84dc9e38ec</RelatedEntityRef>
</MaritalStatus>
<NumberOfDependents>2</NumberOfDependents>
</Person>
</Party>
<Party Type="Guarantor" PrimaryApplicant="No">
<Identifier>ea384b0bf3f5</Identifier>
<Person Sex="Male" FirstHomeBuyer="No" CustomerOfLender="No">
<PersonName>
<NameTitle Value="Mr"/>
<FirstName>Greg</FirstName>
<OtherName>Morty</OtherName>
<Surname>Sanchez</Surname>
</PersonName>
<MaritalStatus Status="DeFacto">
<RelatedEntityRef>b8b0f908b08e</RelatedEntityRef>
</MaritalStatus>
<NumberOfDependents>0</NumberOfDependents>
</Person>
</Party>
<Party Type="Applicant" PrimaryApplicant="No">
<Identifier>ee84dc9e38ec</Identifier>
<Person Sex="Male" FirstHomeBuyer="No" CustomerOfLender="No">
<PersonName>
<NameTitle Value="Mr"/>
<FirstName>Mark</FirstName>
<Surname>Bonkers</Surname>
</PersonName>
<MaritalStatus Status="Married">
<RelatedEntityRef>bd8c65a3ad80</RelatedEntityRef>
</MaritalStatus>
<NumberOfDependents>0</NumberOfDependents>
</Person>
</Party>
</PartySegment>
The desire output:
<Household UniqueID="b8b0f908b08e-Household"
Name="Sanchez Household"
NumberOfAdults="2"
NumberOfDependants="1"/>
<Household UniqueID="bd8c65a3ad80-Household"
Name="Bonkers Household"
NumberOfAdults="2"
NumberOfDependants="2"/>
What i have so far(simplified): This is working for one couple because is not taking in consideration the MaritalStatus.RelatedEntityRef information
<xsl:template match="PartySegment" mode="Household_Couple">
<xsl:for-each-group select="Party[Person/MaritalStatus/#Status = ('DeFacto', 'Married')]" group-by="Person/MaritalStatus/#Status = ('DeFacto', 'Married')">
<xsl:variable name="owner_id" select="Identifier"/>
<Household UniqueID="{concat(Identifier, '-Household')}"
Name="{normalize-space(concat(Person/PersonName/Surname, ' Household'))}"
NumberOfAdults="{'2'}"
NumberOfDependants="{if(Person/Dependent) then count(current-group()/Person/Dependent) else if(Person/NumberOfDependents) then sum(current-group()/Person/NumberOfDependents) else '0'}">
<xsl:apply-templates select="current-group()/Person/Dependent"/>
</Household>
</xsl:for-each-group>
</xsl:template>

If you can move to XSLT 3.0 then I think a composite grouping key sort((Identifier, key('ref', Person/MaritalStatus/RelatedEntityRef)/Identifier)) of the sort of the two related identifiers can solve this:
<xsl:key name="ref" match="Party" use="Identifier"/>
<xsl:template match="PartySegment">
<xsl:for-each-group select="Party[Person/MaritalStatus/#Status = ('DeFacto', 'Married')]"
composite="yes"
group-by="sort((Identifier, key('ref', Person/MaritalStatus/RelatedEntityRef)/Identifier))">
<Household UniqueID="{concat(Identifier, '-Household')}"
Name="{normalize-space(concat(Person/PersonName/Surname, ' Household'))}"
NumberOfAdults="{'2'}"
NumberOfDependants="{if(Person/Dependent) then count(current-group()/Person/Dependent) else if(Person/NumberOfDependents) then sum(current-group()/Person/NumberOfDependents) else '0'}">
</Household>
</xsl:for-each-group>
</xsl:template>
I get
<Household UniqueID="b8b0f908b08e-Household"
Name="Sanchez Household"
NumberOfAdults="2"
NumberOfDependants="1"/>
<Household UniqueID="bd8c65a3ad80-Household"
Name="Bonkers Household"
NumberOfAdults="2"
NumberOfDependants="2"/>
this way with Saxon 9.8 EE inside of oXygen.
For Saxon 9.8 HE it should be possible to rewrite that as
<xsl:key name="ref" match="Party" use="Identifier"/>
<xsl:template match="PartySegment">
<xsl:for-each-group select="Party[Person/MaritalStatus/#Status = ('DeFacto', 'Married')]"
composite="yes"
group-by="Identifier | key('ref', Person/MaritalStatus/RelatedEntityRef)/Identifier">
<Household UniqueID="{concat(Identifier, '-Household')}"
Name="{normalize-space(concat(Person/PersonName/Surname, ' Household'))}"
NumberOfAdults="{'2'}"
NumberOfDependants="{if(Person/Dependent) then count(current-group()/Person/Dependent) else if(Person/NumberOfDependents) then sum(current-group()/Person/NumberOfDependents) else '0'}">
</Household>
</xsl:for-each-group>
</xsl:template>
For XSLT 2.0 where we don't have composite keys we would need to make sure to construct a single key with both components:
<xsl:template match="PartySegment">
<xsl:for-each-group select="Party[Person/MaritalStatus/#Status = ('DeFacto', 'Married')]"
group-by="string-join((Identifier | key('ref', Person/MaritalStatus/RelatedEntityRef)/Identifier), '|')">
<Household UniqueID="{concat(Identifier, '-Household')}"
Name="{normalize-space(concat(Person/PersonName/Surname, ' Household'))}"
NumberOfAdults="{'2'}"
NumberOfDependants="{if(Person/Dependent) then count(current-group()/Person/Dependent) else if(Person/NumberOfDependents) then sum(current-group()/Person/NumberOfDependents) else '0'}">
</Household>
</xsl:for-each-group>
</xsl:template>

Related

XSLT 2.0: Check if string ends with a value from an array

How can I detect that a string ends with a value from a pre-determined array?
Couldn't figure it out myself from other questions on SO because they ask about a complete string match.
Something like this
<xsl:template match="card">
<xsl:variable name="word" select="k" />
<xsl:variable name="obviouslyRussianSuffixes" select="('изм', 'ия', 'ист', 'ёр', 'ца', 'фон')" />
<xsl:if test="ends-with($word, $obviouslyRussianSuffixes)">
<xsl:value-of select="$word" />
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:template>
I think you want the test to be some $suffix in $obviouslyRussianSuffixes satisfies ends-with($word, $suffix).

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

or condition not working as expected

I've the below XML statement
<section level="sect1">
<title><content-style font-style="bold">PRACTICE DIRECTIONS</content-style></title>
</section>
when i try to apply the below condition
<xsl:when test="not(contains(./title/content-style/text(),'PRACTICE DIRECTIONS'))">
<xsl:choose>
<xsl:when test="./section[1]/para/phrase">
<xsl:value-of select="./section[1]/para[1]/phrase"/>
<xsl:for-each select="./section">
<xsl:apply-templates select="." mode="toc"/>
</xsl:for-each>
</xsl:when>
</xsl:choose>
It is working fine
Here I've another condition.
<xsl:when test="not(contains(./title/content-style,'ORDER')) or not(contains(./title/content-style/text(),'PRACTICE DIRECTIONS')) or not(contains(./section[1]/title,'ORDER')) or not(contains(./section[1]/title,'PRACTICE DIRECTIONS'))">
Here this should not let the condition(or the cursor) to get into the inner choose condition as there is not(contains(./title/content-style/text(),'PRACTICE DIRECTIONS')) as one of the conditions.
But here in my case the cursor is moved into the inner choose. Where am I going wrong?
Use AND instead of OR and you'll probably get the result you're after.

Resources