Two XSL files need single final output file - xslt-2.0

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>

Related

How to match template based on condition?

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>

remove encoding="UTF-8"? from <?xml version="1.0" encoding="UTF-8"?> using xslt

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>

How can grouped the TEXT/ELEMENT by xsl:for-each-group element in XSLT 2.0

INPUT XML:
<overline-start id="tie1" specific-use="tie-bar"/>PtCl<sub>2</sub>(P((CH<sub>2</sub>)<sub><italic toggle="yes">n</italic></sub>)<sub>3</sub><overline-end rid="tie1"/>
EXPECTED XML:
<overline id="tie1" specific-use="tie-bar">PtCl<sub>2</sub>(P((CH<sub>2</sub>)<sub><italic toggle="yes">n</italic></sub>)<sub>3</sub></overline>
MY XSLT 2.0 Code:
<xsl:template match="overline-start">
<xsl:for-each-group select="self::overline-start" group-adjacent="self::overline-start[following-sibling::overline-end]">
<xsl:for-each select="current-group()">
<overline>
<xsl:apply-templates select="#*"/>
<xsl:copy-of select="current-group()"/>
</overline>
</xsl:for-each>
As you mentioned the requirement in comments, I tried it #Martin Honnen 's way:
Assuming input as:
<?xml version="1.0" encoding="UTF-8"?>
<p>
<overline-start id="tie1" specific-use="tie-bar"/>PtCl<sub>2</sub>(P((CH<sub>2</sub>)<sub><italic toggle="yes">n</italic></sub>)<sub>3</sub><overline-end rid="tie1"/>
</p>
A 2.0 solution can be:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output omit-xml-declaration="yes" indent="no" />
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*" />
</xsl:copy>
</xsl:template>
<xsl:template match="p">
<overline>
<xsl:for-each-group select="* | text()" group-starting-with="overline-start">
<xsl:for-each-group select="current-group()" group-ending-with="overline-end">
<xsl:apply-templates select="#*" />
<xsl:sequence select="(current-group() except .) [position() != last()]" />
</xsl:for-each-group>
</xsl:for-each-group>
</overline>
</xsl:template>
</xsl:stylesheet>
http://xsltfiddle.liberty-development.net/bnnZW8/1

XSL:KEY Function for external file

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

Extracting value from External xml based on some rule in xsl

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.

Resources