Here is my source XML which I'm trying to transform based on values of <City>
<?xml version="1.0" encoding="UTF-8"?>
<Workers>
<Worker>
<EmpID>12345</EmpID>
<City>NYC</City>
<Allowance>
<Type>Meal</Type>
<Amount>150</Amount>
</Allowance>
<Allowance>
<Type>Gym</Type>
<Amount>200</Amount>
</Allowance>
</Worker>
<Worker>
<EmpID>56789</EmpID>
<City>SFO</City>
<Base>
<BaseType>General</BaseType>
<BaseAmount>1000</BaseAmount>
</Base>
</Worker>
<Worker>
<EmpID>18978</EmpID>
<City>LAX</City>
<Base>
<BaseType>General</BaseType>
<BaseAmount>3000</BaseAmount>
</Base>
</Worker>
</Workers>
I'm attempting to transform as below. Transformation doesn't need be to applied if the value of <City> is either NYC or SFO
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<SOAP-ENV:Body xmlns:SOAP-ENV="http://www.w3.org/2001/12/soap-envelope">
<m:GetQuotationResponse xmlns:m = "http://www.example.com">
<m:Worker>12345</m:Worker>
<m:Location>NYC</m:Location>
<m:Expense>
<m:ExpenseType>Meal</m:ExpenseType>
<m:Amount>150</m:Amount>
</m:Expense>
<m:Expense>
<m:ExpenseType>Gym</m:ExpenseType>
<m:Amount>200</m:Amount>
</m:Expense>
</m:GetQuotationResponse>
</SOAP-ENV:Body>
<SOAP-ENV:Body xmlns:SOAP-ENV="http://www.w3.org/2001/12/soap-envelope">
<m:GetQuotationResponse xmlns:m = "http://www.example.com">
<m:Worker>56789</m:Worker>
<m:Location>SFO</m:Location>
<m:Expense>
<m:ExpenseType>General</m:ExpenseType>
<m:Amount>1000</m:Amount>
</m:Expense>
</m:GetQuotationResponse>
</SOAP-ENV:Body>
</Root>
This is my attempt
<?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:SOAP-ENV = "http://www.w3.org/2001/12/soap-envelope"
xmlns:m = "http://www.example.com"
exclude-result-prefixes="xs m SOAP-ENV"
version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Worker[City='NYC']">
<Root>
<SOAP-ENV:Body xmlns:m = "http://www.example.com">
<m:GetQuotationResponse>
<m:Worker><xsl:value-of select="EmpID"/></m:Worker>
<m:Location><xsl:value-of select="City"/></m:Location>
<xsl:for-each select="Allowance">
<m:Expense>
<m:ExpenseType><xsl:value-of select="Type"/></m:ExpenseType>
<m:Amount><xsl:value-of select="Amount"/></m:Amount>
</m:Expense>
</xsl:for-each>
</m:GetQuotationResponse>
</SOAP-ENV:Body>
</Root>
</xsl:template>
<xsl:template match="Worker[City='SFO']">
<Root>
<SOAP-ENV:Body xmlns:m = "http://www.example.com">
<m:GetQuotationResponse>
<m:Worker><xsl:value-of select="EmpID"/></m:Worker>
<m:Location><xsl:value-of select="City"/></m:Location>
<xsl:for-each select="Base">
<m:Expense>
<m:ExpenseType><xsl:value-of select="BaseType"/></m:ExpenseType>
<m:Amount><xsl:value-of select="BaseAmount"/></m:Amount>
</m:Expense>
</xsl:for-each>
</m:GetQuotationResponse>
</SOAP-ENV:Body>
</Root>
</xsl:template>
</xsl:stylesheet>
I have two issues(or more)
Couldn't get <Root> as the Parent node
Templates which are not matching values of <City> also returned. I wanted to match only <xsl:template match="Worker[City='NYC']"> or <xsl:template match="Worker[City='SFO']">
Current Output
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<SOAP-ENV:Body xmlns:SOAP-ENV="http://www.w3.org/2001/12/soap-envelope">
<m:GetQuotationResponse xmlns:m="http://www.example.com">
<m:Worker>12345</m:Worker>
<m:Location>NYC</m:Location>
<m:Expense>
<m:ExpenseType>Meal</m:ExpenseType>
<m:Amount>150</m:Amount>
</m:Expense>
<m:Expense>
<m:ExpenseType>Gym</m:ExpenseType>
<m:Amount>200</m:Amount>
</m:Expense>
</m:GetQuotationResponse>
</SOAP-ENV:Body>
</Root>
<Root>
<SOAP-ENV:Body xmlns:SOAP-ENV="http://www.w3.org/2001/12/soap-envelope">
<m:GetQuotationResponse xmlns:m="http://www.example.com">
<m:Worker>56789</m:Worker>
<m:Location>SFO</m:Location>
<m:Expense>
<m:ExpenseType>General</m:ExpenseType>
<m:Amount>1000</m:Amount>
</m:Expense>
</m:GetQuotationResponse>
</SOAP-ENV:Body>
</Root>
18978
LAX
General
3000
Any help is appreciated to get this working using xslt 2.0 or xslt 3.0. Thank you
I'm posting the first solution that Martin Honnen has suggested.
<?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:SOAP-ENV = "http://www.w3.org/2001/12/soap-envelope"
xmlns:m = "http://www.example.com"
exclude-result-prefixes="xs m SOAP-ENV"
version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Workers">
<Root>
<xsl:apply-templates/>
</Root>
</xsl:template>
<xsl:template match="Worker[City='NYC']">
<SOAP-ENV:Body xmlns:m = "http://www.example.com">
<m:GetQuotationResponse>
<m:Worker><xsl:value-of select="EmpID"/></m:Worker>
<m:Location><xsl:value-of select="City"/></m:Location>
<xsl:for-each select="Allowance">
<m:Expense>
<m:ExpenseType><xsl:value-of select="Type"/></m:ExpenseType>
<m:Amount><xsl:value-of select="Amount"/></m:Amount>
</m:Expense>
</xsl:for-each>
</m:GetQuotationResponse>
</SOAP-ENV:Body>
</xsl:template>
<xsl:template match="Worker[City='SFO']">
<SOAP-ENV:Body xmlns:m = "http://www.example.com">
<m:GetQuotationResponse>
<m:Worker><xsl:value-of select="EmpID"/></m:Worker>
<m:Location><xsl:value-of select="City"/></m:Location>
<xsl:for-each select="Base">
<m:Expense>
<m:ExpenseType><xsl:value-of select="BaseType"/></m:ExpenseType>
<m:Amount><xsl:value-of select="BaseAmount"/></m:Amount>
</m:Expense>
</xsl:for-each>
</m:GetQuotationResponse>
</SOAP-ENV:Body>
</xsl:template>
<xsl:template match="Worker[not(City = ('SFO', 'NYC'))]"/>
</xsl:stylesheet>
Here is what alternate solution returns. I'm not sure how this solution can be modified to get expected output since City='SFO' has different sibling node <Base> than City='NYC'
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<SOAP-ENV:Body xmlns:SOAP-ENV="http://www.w3.org/2001/12/soap-envelope">
<m:GetQuotationResponse xmlns:m="http://www.example.com">
<m:Worker>12345</m:Worker>
<m:Location>NYC</m:Location>
<m:Expense>
<m:ExpenseType>Meal</m:ExpenseType>
<m:Amount>150</m:Amount>
</m:Expense>
<m:Expense>
<m:ExpenseType>Gym</m:ExpenseType>
<m:Amount>200</m:Amount>
</m:Expense>
</m:GetQuotationResponse>
</SOAP-ENV:Body>
<SOAP-ENV:Body xmlns:SOAP-ENV="http://www.w3.org/2001/12/soap-envelope">
<m:GetQuotationResponse xmlns:m="http://www.example.com">
<m:Worker>56789</m:Worker>
<m:Location>SFO</m:Location>
</m:GetQuotationResponse>
</SOAP-ENV:Body>
</Root>
Following part is missing from the output
<m:Expense>
<m:ExpenseType>General</m:ExpenseType>
<m:Amount>1000</m:Amount>
</m:Expense>
Alternate solution suggested by #Martin Honnen with some minor tweaks also provide desired output.
<?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:SOAP-ENV = "http://www.w3.org/2001/12/soap-envelope"
xmlns:m = "http://www.example.com"
exclude-result-prefixes="xs m SOAP-ENV"
version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Workers">
<Root>
<xsl:apply-templates select="Worker[City = ('SFO', 'NYC')]"/>
</Root>
</xsl:template>
<xsl:template match="Worker">
<SOAP-ENV:Body xmlns:m = "http://www.example.com">
<m:GetQuotationResponse>
<m:Worker><xsl:value-of select="EmpID"/></m:Worker>
<m:Location><xsl:value-of select="City"/></m:Location>
<xsl:for-each select="Allowance">
<m:Expense>
<m:ExpenseType><xsl:value-of select="Type"/></m:ExpenseType>
<m:Amount><xsl:value-of select="Amount"/></m:Amount>
</m:Expense>
</xsl:for-each>
<xsl:for-each select="Base"> <!-- This part was included to get desired output without having to use more than one templates -->
<m:Expense>
<m:ExpenseType><xsl:value-of select="BaseType"/></m:ExpenseType>
<m:Amount><xsl:value-of select="BaseAmount"/></m:Amount>
</m:Expense>
</xsl:for-each>
</m:GetQuotationResponse>
</SOAP-ENV:Body>
</xsl:template>
</xsl:stylesheet>
Start with a template
<xsl:template match="Workers">
<Root>
<xsl:apply-templates/>
</Root>
</xsl:template>
then map your selected Workers to a SOAP body with a single template using e.g. <xsl:template match="Worker[City = ('SFO', 'NYC')]"> or <xsl:template match="Worker[City = 'SFO'] | Worker[City = 'NYC']">, if you prefer.
For other Workers, set up an empty template e.g. <xsl:template match="Worker[not(City = ('SFO', 'NYC'))]"/>.
As an alternative, you can of course just use a template matching Worker to map to a SOAP body and make your desired selection in the apply-templates of the first template I have show, i.e. change that to <xsl:apply-templates select="Worker[City = ('SFO', 'NYC')]"/>, that way you also ensure that only the wanted Workers are processed e.g.
<xsl:template match="Workers">
<Root>
<xsl:apply-templates select="Worker[City = ('SFO', 'NYC')]"/>
</Root>
</xsl:template>
<xsl:template match="Worker">
<SOAP-ENV:Body xmlns:m = "http://www.example.com">
<m:GetQuotationResponse>
<m:Worker><xsl:value-of select="EmpID"/></m:Worker>
<m:Location><xsl:value-of select="City"/></m:Location>
<xsl:for-each select="Allowance">
<m:Expense>
<m:ExpenseType><xsl:value-of select="Type"/></m:ExpenseType>
<m:Amount><xsl:value-of select="Amount"/></m:Amount>
</m:Expense>
</xsl:for-each>
</m:GetQuotationResponse>
</SOAP-ENV:Body>
</xsl:template>
Related
I have a input file and two XSL files test1.xsl, test2.xsl
test1.xsl file transforming on input file and generating test1-output.xml
test2.xsl file transforming on test1-output.xml and generating the final output
Requirement:
I am using XSLT 2.0
I want run at a time both xslt files transform on input file and generate the final output.
How to do this requirement, Please suggest!
Input file:
<?xml version="1.0" encoding="UTF-8"?>
<k>
<page>content here</page>
<page1>content here</page1>
</k>
test1.xsl file:
<?xml version="1.0"qqq encoding="UTF-8"?>
<xsl:stylesheet xmqlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output indent="yes" method="xml"/>
<xsl:template match="#*| node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="page">
<page>
<kita>
<xsl:apply-templates/>
</kita>
</page>
</xsl:template>
</xsl:stylesheet>
output of test1.xsl
<?xml version="1.0" encoding="UTF-8"?>
<k>
<page>
<kita>content here</kita>
</page>
<page1>content here</page1>
</k>
test2.xsl
<?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"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output indent="yes" method="xml"/>
<xsl:template match="#*| node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="kita">
<kita>
<kita1>
<xsl:apply-templates/>
</kita1>
</kita>
</xsl:template>
</xsl:stylesheet>
This is my final xml output from the 2nd XSLT file:
<?xml version="1.0" encoding="UTF-8"?>
<k>
<page>
<kita>
<kita1>content here</kita1>
</kita>
</page>
<page1>content here</page1>
</k>
Thanks in advance
In XSLT 3 you could write a stylesheet with two parameters calling fn:transform twice e.g.
<xsl:param name="xslt1" as="document-node()"/>
<xsl:param name="xslt2" as="document-node()"/>
<xsl:template match="/">
<xsl:sequence
select="
transform(map {
'stylesheet-node' : $xslt1,
'source-node' : .
})?output ! transform(map {
'stylesheet-node' : $xslt2,
'source-node' : .
})?output"/>
</xsl:template>
or if you want to pass in the file URIs
<xsl:param name="xslt1" as="xs:string">test1.xsl</xsl:param>
<xsl:param name="xslt2" as="xs:string">test2.xsl</xsl:param>
<xsl:template match="/">
<xsl:sequence
select="
transform(map {
'stylesheet-node' : doc($xslt1),
'source-node' : .
})?output ! transform(map {
'stylesheet-node' : doc($xslt2),
'source-node' : .
})?output"/>
</xsl:template>
I ma trying to add 2 names spaces and remove the encoding="UTF-8"?, but I unable to delete the encoding="UTF-8".
input xml:
<?xml version="1.0" encoding="UTF-8"?>
<ACCEPTATION Date_de_Production="2019-06-20T19:45:48.470-04:00"
Id_fichier_CAM="CAM_erreur piece 395 balise absent non permises.xml"
Artwork="Artwork-6" Environnement="UNIT" Nombre_Pieces_Lues="6"
Nombre_Pieces_Invalides="6" Statut_Acceptation_Statut="ACCEPTE"
Statut_Acceptation_Code_Rejet="000" Traitement_Producteur="GPH321">
<PIECE>
<CAM_Type_Piece>CAMPS</CAM_Type_Piece>
<CAM_Statut>NON CHARGE</CAM_Statut>
</PIECE>
<PIECE>
<CAM_Type_Piece>CAMPS</CAM_Type_Piece>
<CAM_Statut>NON CHARGE</CAM_Statut>>
</PIECE>
</ACCEPTATION>
xslt code: please correct the code and help me out to get the required output.
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<!-- <xsl:output method="xml" omit-xml-declaration="yes"/>-->
<xsl:template match="#*|text()|comment()|processing-instruction()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ACCEPTATION">
<ACCEPTATION xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsl:apply-templates select="#*|node()"/>
</ACCEPTATION>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
required out xml: in the output xml encoding shouldn't be present.
<?xml version="1.0">
<ACCEPTATION xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
Artwork="Artwork-6"
Date_de_Production="2019-06-20T19:45:48.470-04:00"
Environnement="UNIT"
Id_fichier_CAM="CAM_erreur piece 395 balise absent non
permises.xml"
Nombre_Pieces_Invalides="6"
Nombre_Pieces_Lues="6"
Statut_Acceptation_Code_Rejet="000"
Statut_Acceptation_Statut="ACCEPTE"
Traitement_Producteur="GPH321">
<PIECE>
<CAM_Type_Piece>CAMPS</CAM_Type_Piece>
<CAM_Statut>NON CHARGE</CAM_Statut>
</PIECE>
<PIECE>
<CAM_Type_Piece>CAMPS</CAM_Type_Piece>
<CAM_Statut>NON CHARGE</CAM_Statut>>
</PIECE>
</ACCEPTATION>
check this code:-
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<!-- <xsl:output method="xml" omit-xml-declaration="yes"/>-->
<xsl:template match="#*|text()|comment()|processing-instruction()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ACCEPTATION">
<xsl:text disable-output-escaping="yes"><![CDATA[<?xml version="1.0"?>]]></xsl:text>
<ACCEPTATION xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsl:apply-templates select="#*|node()"/>
</ACCEPTATION>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
I have an issue in key function, key function not running in following code.
my input is
XML (Keys.xml)
<?xml version="1.0" encoding="UTF-8"?>
<Keys>
<Key year="2001" name="ABC"/>
<Key year="2002" name="BCA"/>
</Keys>
XML to convert
<?xml version="1.0" encoding="UTF-8"?>
<p>
<text> .. .. <key>ABC</key> ...</text>
<text> .. .. <key>BCA</key> ...</text>
</p>
XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:key name="keydata" match="*[name() = document('keys.xml')]/Keys/Key" use="#name"/>
<xsl:template match="key">
<xsl:copy>
<xsl:attribute name="ref"><xsl:value-of select="key('keydata', .)/#year"/></xsl:attribute>
<xsl:value-of select="."/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Output
<p>
<text> .. .. <key ref="">ABC</key> ...</text>
<text> .. .. <key ref="">BCA</key> ...</text>
</p>
Desired Ouput
<p>
<text> .. .. <key ref="2001">ABC</key> ...</text>
<text> .. .. <key ref="2002">BCA</key> ...</text>
</p>
This should work:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:variable name="keys" select="document('keys.xml')" as="document-node()"/>
<xsl:key name="keydata" match="Key" use="#name"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="key">
<xsl:copy>
<xsl:attribute name="ref"><xsl:value-of select="$keys/key('keydata', current())/#year"/></xsl:attribute>
<xsl:value-of select="."/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
In the XSL specification, there's an example entitled "Example: Using Keys to Reference other Documents" that exactly matches your use case.
This is the resulting document:
<?xml version="1.0" encoding="UTF-8"?>
<p>
<text> .. .. <key ref="2001">ABC</key> ...</text>
<text> .. .. <key ref="2002">BCA</key> ...</text>
</p>
Change <xsl:key name="keydata" match="*[name() = document('keys.xml')]/Keys/Key" use="#name"/> to <xsl:key name="keydata" match="Keys/Key" use="#name"/> and then <xsl:attribute name="ref"><xsl:value-of select="key('keydata', .)/#year"/></xsl:attribute> to <xsl:attribute name="ref" select="key('keydata', . doc('Keys.xml'))/#year"/></xsl:attribute>.
Can you please suggest xslt code on how to get the results based on the below
xml on group by Week value. The expected output should be:
Year Week Tot Hrs Ben Hrs
2015 33 80.7 0
2015 34 120.7 0
Advance thanks for your help
XML:
<?xml version="1.0" encoding="UTF-8"?>
-<wd:Report_Data xmlns:wd="urn:com.workday.report/TLB024_TEST">
-<wd:Report_Entry>
-<wd:PAYROLL_RESULT_LINE>
<wd:FISCAL_YEAR>2015</wd:FISCAL_YEAR>
<wd:FISCAL_WEEK>33</wd:FISCAL_WEEK>
<wd:TOT_HRS>40</wd:TOT_HRS>
<wd:BEN_HRS>0</wd:BEN_HRS>
</wd:PAYROLL_RESULT_LINE>
-<wd:PAYROLL_RESULT_LINE>
<wd:FISCAL_YEAR>2015</wd:FISCAL_YEAR>
<wd:FISCAL_WEEK>33</wd:FISCAL_WEEK>
<wd:TOT_HRS>0.07</wd:TOT_HRS>
<wd:BEN_HRS>0</wd:BEN_HRS>
</wd:PAYROLL_RESULT_LINE>
-<wd:PAYROLL_RESULT_LINE>
<wd:FISCAL_YEAR>2015</wd:FISCAL_YEAR>
<wd:FISCAL_WEEK>34</wd:FISCAL_WEEK>
<wd:TOT_HRS>40</wd:TOT_HRS>
<wd:BEN_HRS>0</wd:BEN_HRS>
</wd:PAYROLL_RESULT_LINE>
-<wd:PAYROLL_RESULT_LINE>
<wd:FISCAL_YEAR>2015</wd:FISCAL_YEAR>
<wd:FISCAL_WEEK>34</wd:FISCAL_WEEK>
<wd:TOT_HRS>0.07</wd:TOT_HRS>
<wd:BEN_HRS>0</wd:BEN_HRS>
</wd:PAYROLL_RESULT_LINE>
</wd:Report_Entry>
-<wd:Report_Entry>
-<wd:PAYROLL_RESULT_LINE>
<wd:FISCAL_YEAR>2015</wd:FISCAL_YEAR>
<wd:FISCAL_WEEK>33</wd:FISCAL_WEEK>
<wd:TOT_HRS>40</wd:TOT_HRS>
<wd:BEN_HRS>0</wd:BEN_HRS>
</wd:PAYROLL_RESULT_LINE>
-<wd:PAYROLL_RESULT_LINE>
<wd:FISCAL_YEAR>2015</wd:FISCAL_YEAR>
<wd:FISCAL_WEEK>34</wd:FISCAL_WEEK>
<wd:TOT_HRS>40</wd:TOT_HRS>
<wd:BEN_HRS>0</wd:BEN_HRS>
</wd:PAYROLL_RESULT_LINE>
</wd:Report_Entry>
-<wd:Report_Entry>
</wd:Report_Data>
XSLT :
This is the xslt code, I tried not able to get the desire result.
<?xml version='1.0'?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:wd="urn:com.workday.report/TLB024_TEST" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:template match="/|*">
<xsl:copy>
<xsl:apply-templates select="*" />
</xsl:copy>
</xsl:template>
<xsl:template match="wd:Report_Entry">
<File xmlns:xtt="urn:com.workday/xtt">
<xsl:for-each select="wd:PAYROLL_RESULT_LINE">
<Record>
<xsl:variable name="Group" select="../wd:PAYROLL_RESULT_LINE[((wd:FISCAL_YEAR=current()/wd:FISCAL_YEAR) and (wd:FISCAL_WEEK=current()/wd:FISCAL_WEEK)]" />
<xsl:if test="generate-id()=generate-id($Group[1])">
<xsl:copy>
<fiscal_year xtt:align="left"><xsl:value-of select="wd:FISCAL_YEAR"/></fiscal_year>
<fiscal_week xtt:align="left"><xsl:value-of select="wd:FISCAL_WEEK"/></fiscal_week>
<tot_hrs xtt:fixedLength="7" xtt:align="left"><xsl:value-of select="format-number(sum($Group/wd:TOT_HRS), '0.##')"/></tot_hrs>
<ben_hrs xtt:fixedLength="7" xtt:align="left"><xsl:value-of select="format-number(sum($Group/wd:BEN_HRS), '0.##')"/></ben_hrs>
<Filler><xsl:text>
</xsl:text></Filler>
</xsl:copy>
</xsl:if>
</Record>
</xsl:for-each>
</File>
</xsl:template>
</xsl:stylesheet>
If you are using XSLT 2.0, this is a very simple grouping problem:
<xsl:for-each-group select="wd:PAYROLL_RESULT_LINE"
group-by="concat(wd:FISCAL_YEAR, '/', wd:FISCAL_WEEK)">
<Record>
<fiscal_year xtt:align="left"><xsl:value-of select="wd:FISCAL_YEAR"/></fiscal_year>
<fiscal_week xtt:align="left"><xsl:value-of select="wd:FISCAL_WEEK"/></fiscal_week>
<tot_hrs xtt:fixedLength="7" xtt:align="left"><xsl:value-of select="format-number(sum(current-group()/wd:TOT_HRS), '0.##')"/></tot_hrs>
<ben_hrs xtt:fixedLength="7" xtt:align="left"><xsl:value-of select="format-number(sum(current-group()/wd:BEN_HRS), '0.##')"/></ben_hrs>
<Filler><xsl:text>
</xsl:text></Filler>
</Record>
</xsl:for-each-group>
This is input xml input.xml
<root>
<bodytext>
<remotelink refptid="HKBL1.0001.lohk.CAP65">some text</remotelink>
<remotelink refptid="HKBL1.0001.lohk.CAP199999">some text</remotelink>
</bodytext>
</root>
This is Prop.xml
<?xml version="1.0" encoding="utf-8"?>
<properties>
<code dpsi="0BZG" docid="asdww">HKBL1.0001.lohk.CAP65</code>
<code dpsi="0BZH" docid="navin">HKBL1.0002.aohk.CAP383</code>
<code no="3">345</code>
</properties>
This is desired output
<root>
<bodytext>
<remotelink refptid="HKBL1.0001.lohk.CAP65" dpsi="0BZG" docid="asdww">some text</remotelink>
<remotelink refptid="HKBL1.0001.lohk.CAP199999">some text</remotelink>
</bodytext>
</root>
IF prop.xml code/text matches remotelink/#refptid than copy attribute of prop.xml to remotelink otherwise no changes in remotelink.
This is the XSLT I have written. So far I am not getting result for unmatched condition:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlsx="http://www.stylusstudio.com/XSLT/XLSX" xmlns:spml="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:saxon="http://saxon.sf.net/" version="2.0">
<xsl:template match="#*|node()" name="root">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="remotelink[#service='DOC-ID']" name="t-remote">
<xsl:variable name="refptid" select="./#refpt"/>
<xsl:variable name="path" select="doc('file:/C:/Users/DalalNS/Desktop/xslt/prop.xml')"/>
<xsl:for-each select="$path/properties/code">
<xsl:choose>
<xsl:when test="./text()=$refptid">
<xsl:element name="remotelink">
<xsl:attribute name="DOC-ID" select="./#docid"/>
<xsl:attribute name="dpsi" select="./#dpsi"/>
<xsl:attribute name="refpt" select="$refptid"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:if test="./#docrefid"/>
</xsl:template>
</xsl:stylesheet>
<xsl:template match="remotelink[#service='DOC-ID']"> will never never be triggered, there's no service attribute on the <remotelink> element. Moreover, you don't retrieve the correct attribute (refpt instead of refptid)
This XSL transformation should do the job:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xlsx="http://www.stylusstudio.com/XSLT/XLSX" xmlns:spml="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:saxon="http://saxon.sf.net/" version="2.0">
<xsl:variable name="props.doc" select="doc('file:/C:/Users/DalalNS/Desktop/xslt/prop.xml')/properties" />
<xsl:template match="#*|node()" name="root">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="remotelink" name="t-remote">
<xsl:variable name="refptid" select="./#refptid"/>
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:if test="$props.doc/code[. = $refptid]">
<xsl:apply-templates select="$props.doc/code[. = $refptid]/#*"/>
</xsl:if>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
This is the result of the transformation:
<?xml version="1.0" encoding="UTF-8"?><root>
<bodytext>
<remotelink refptid="HKBL1.0001.lohk.CAP65" dpsi="0BZG" docid="asdww">some text</remotelink>
<remotelink refptid="HKBL1.0001.lohk.CAP199999">some text</remotelink>
</bodytext>
</root>
I would simply define a global parameter or variable <xsl:variable name="path" select="doc('file:/C:/Users/DalalNS/Desktop/xslt/prop.xml')"/>, then set up a key <xsl:key name="prop" match="code" use="."/>, and then use that in a template
<xsl:template match="remotelink[key('prop', #refptid, $path)]">
<xsl:copy>
<xsl:copy-of select="key('prop', #refptid, $path)/#*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
that, together with your first template, should suffice.