XML to pipe-delimited - How to copy/duplicate data to different rows - xslt

I'm new to XSLT and trying to transform from XML to pipe-delimited format. The problem that I'm having is that in the output, each claim has to be duplicated for each service line.
Expected Output:
EP030315706890704|TESTSUBMITTER|FAMILY HEALTHCARE|1122334455|1|99214|179.00
EP030315706890704|TESTSUBMITTER|FAMILY HEALTHCARE|1122334455|2|2000F|0.00
EP030315706890705|TESTSUBMITTER2|FAMILY HEALTHCARE|1122334455|1|99214|179.00
EP030315706890705|TESTSUBMITTER2|FAMILY HEALTHCARE|1122334455|2|2000F|0.00
Input XML looks as follows:
<payloadContainer>
<afile>
<clm>
<hdr>
<corn>EP030315706890704</corn>
<idSend>112233445</idSend>
<nmSend>TESTSUBMITTER</nmSend>
</hdr>
<provBill>
<name>
<nmOrg>FAMILY HEALTHCARE</nmOrg>
</name>
<id T="XX" P="P">1122334455</id>
</provBill>
<serv S="1">
<numLine>1</numLine>
<prof>
<px L="S">
<cdPx T="HC">99214</cdPx>
</px>
<amtChrg>179.00</amtChrg>
</prof>
</serv>
<serv S="2">
<numLine>2</numLine>
<prof>
<px L="S">
<cdPx T="HC">2000F</cdPx>
</px>
<amtChrg>0.00</amtChrg>
</prof>
</serv>
</clm>
<clm>
<hdr>
<corn>EP030315706890705</corn>
<idSend>112233445</idSend>
<nmSend>TESTSUBMITTER2</nmSend>
</hdr>
<provBill>
<name>
<nmOrg>FAMILY HEALTHCARE</nmOrg>
</name>
<id T="XX" P="P">1122334455</id>
</provBill>
<serv S="1">
<numLine>1</numLine>
<prof>
<px L="S">
<cdPx T="HC">99214</cdPx>
</px>
<amtChrg>179.00</amtChrg>
</prof>
</serv>
<serv S="2">
<numLine>2</numLine>
<prof>
<px L="S">
<cdPx T="HC">2000F</cdPx>
</px>
<amtChrg>0.00</amtChrg>
</prof>
</serv>
</clm>
</afile>
</payloadContainer>
Desired output XML:
<Table>
<row>
.... All the fields represented here.
</row>
</Table>
Possible solution: https://www.dropbox.com/s/wzvtzw7ihtgxx9o/claimtoRedshift.xsl
This scenario creates two row's dynamically. However, I'm still stuck at how to duplicate for each service line.

I don't see the connection of the linked XSLT to the question presented here. AFAICT, the following stylesheet will return the expected pipe-delimited output:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/payloadContainer">
<xsl:for-each select="afile/clm">
<xsl:variable name="common">
<xsl:value-of select="hdr/corn"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="hdr/nmSend"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="provBill/name/nmOrg"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="provBill/id"/>
<xsl:text>|</xsl:text>
</xsl:variable>
<xsl:for-each select="serv">
<xsl:value-of select="$common"/>
<xsl:value-of select="numLine"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="prof/px/cdPx"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="prof/amtChrg"/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Related

How to put a field coming from <xsl: value-of select = "#" /> inside a tag?

I can not add within a tag a field with the (<xsl:value-of select=)
I'm creating an XSLT template that transforms data from an Excel into XML. Everything is working fine but now I wanted to add to the userdata tag the username of excel (#User_Name).
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<tXML>
<Header>
<Source>TESTE</Source>
<Action_Type>Upgrade</Action_Type>
<Message_Type>User</Message_Type>
<Company_ID>200000002</Company_ID>
<Msg_Locale>English (United Kingdom)</Msg_Locale>
<Internal_Date_Time_Stamp>08/09/2017 17:35:00</Internal_Date_Time_Stamp>
</Header>
<Message>
<xsl:for-each select="//rs:data">
<xsl:apply-templates/>
</xsl:for-each>
</Message>
</tXML>
</xsl:template>
<xsl:template match="//z:row">
<UserData User_Name="{#User_Name}">
<xsl:value-of select="#User_Name"/>
<User>
<Company_Name>
<xsl:value-of select="#Company_Name"/>
</Company_Name>
<Location_Name>
<xsl:value-of select="#Location_Name"/>
</Location_Name>
<Role_Name>
<xsl:value-of select="#Role_Name"/>
</Role_Name>
<User_Name>
<xsl:value-of select="#User_Name"/>
</User_Name>
<First_Name>
<xsl:value-of select="#First_Name"/>
</First_Name>
<Last_Name>
<xsl:value-of select="#Last_Name"/>
</Last_Name>
<Solutions>
<RestrictedSolution>TESTE</RestrictedSolution>
</Solutions>
</User>
</UserData>
</xsl:template>
</xsl:stylesheet>

XSLT - Why are multiple nodes getting merged in the output ( Group By)

All-
I am trying to understand the root cause for 2 nodes getting merged.
The input XML
<?xml version='1.0' encoding='UTF-8'?>
<Employees>
<Employee>
<Employee_ID>E00001</Employee_ID>
<Legal_Name Descriptor="John Doe" />
<lastName>Doe</lastName>
<firstName>John</firstName>
<P_From_Date>2015-04-01-08:00</P_From_Date>
<P_End_Date>2015-12-31-08:00</P_End_Date>
<Transaction>
<Plan Descriptor="Plan A" />
<effective_date>2015-03-22-08:00</effective_date>
<end_date>2015-10-22</end_date>
<Annual_Cost>6000</Annual_Cost>
</Transaction>
<Transaction>
<Plan Descriptor="Plan A" />
<effective_date>2015-02-03-08:00</effective_date>
<Annual_Cost>4000</Annual_Cost>
</Transaction>
<Transaction>
<Plan Descriptor="Plan A" />
<effective_date>2013-02-03-08:00</effective_date>
<Annual_Cost>3000</Annual_Cost>
</Transaction>
<Transaction>
<Plan Descriptor="Plan B" />
<effective_date>2014-12-03-08:00</effective_date>
<Annual_Cost>12000</Annual_Cost>
</Transaction>
<Transaction>
<Plan Descriptor="Plan B" />
<effective_date>2014-10-03-08:00</effective_date>
<Annual_Cost>1000</Annual_Cost>
</Transaction>
</Employee>
<Employee>
<Employee_ID>E00002</Employee_ID>
<Legal_Name Descriptor="John Doe" />
<lastName>Test</lastName>
<firstName>Jane</firstName>
<P_From_Date>2015-01-01-08:00</P_From_Date>
<Transaction>
<Plan Descriptor="Plan D" />
<effective_date>2015-05-22-08:00</effective_date>
<Annual_Cost>12000</Annual_Cost>
</Transaction>
<Transaction>
<Plan Descriptor="Plan D" />
<effective_date>2014-03-01-08:00</effective_date>
<Annual_Cost>9000</Annual_Cost>
</Transaction>
<Transaction>
<Plan Descriptor="Plan C" />
<effective_date>2014-12-03-08:00</effective_date>
<Annual_Cost>3000</Annual_Cost>
</Transaction>
<Transaction>
<Plan Descriptor="Plan C" />
<effective_date>2013-01-03-08:00</effective_date>
<Annual_Cost>3000</Annual_Cost>
</Transaction>
</Employee>
</Employees>
And the XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<!-- TODO customize transformation rules
syntax recommendation http://www.w3.org/TR/xslt
-->
<xsl:variable name="newline" select="'
'"/>
<xsl:variable name="delimiter">,</xsl:variable>
<xsl:variable name="qualifier">
<xsl:text>"</xsl:text>
</xsl:variable>
<xsl:template match="/Employees">
<EES>
<xsl:apply-templates/>
</EES>
</xsl:template>
<xsl:template match="Employee">
<EE>
<EID>
<xsl:value-of select="Employee_ID" />
</EID>
<FULNAME>
<xsl:value-of select="Legal_Name/#Descriptor"/>
</FULNAME>
<LNAME>
<xsl:value-of select="lastName"/>
</LNAME>
<FNAME>
<xsl:value-of select="firstName"/>
</FNAME>
<xsl:variable name="bework">
<xsl:for-each-group select="Transaction" group-by="Plan/#Descriptor" >
<berow>
<CurrentGroup>
<xsl:value-of select="current-grouping-key()"/>
</CurrentGroup>
<parm_from_date><xsl:value-of select="../P_From_Date" /></parm_from_date>
<xsl:for-each select="current-group()">
<begin-date><xsl:copy-of select="effective_date" /></begin-date>
<include-flag >
<xsl:choose>
<xsl:when test="xs:date( substring(effective_date,1,10)) >= xs:date(substring(../P_From_Date,1,10))">
<xsl:text>Y</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>N</xsl:text>
</xsl:otherwise>
</xsl:choose>
</include-flag>
<adj-begin-date>
<xsl:choose>
<xsl:when test="xs:date(effective_date) >= xs:date(../P_From_Date_1) ">
<xsl:value-of select="effective_date"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="../P_From_Date_1"/>
</xsl:otherwise>
</xsl:choose>
</adj-begin-date>
<end_date>
<xsl:value-of select="current-group()/end_date"/>
</end_date>
<Cost>
<xsl:value-of select="Annual_Cost"/>
</Cost>
</xsl:for-each>
</berow>
</xsl:for-each-group>
</xsl:variable>
<xsl:for-each select="$bework/berow">
<CGR>
<xsl:value-of select="CurrentGroup" />
</CGR>
<PFRMDT>
<xsl:value-of select="parm_from_date" />
</PFRMDT>
<BDT>
<xsl:value-of select="begin-date" />
</BDT>
<FLAG>
<xsl:value-of select="include-flag" />
</FLAG>
<ADJBGNDT>
<xsl:value-of select="$qualifier"/>
</ADJBGNDT>
<EDATE>
<xsl:value-of select="$qualifier"/>
</EDATE>
<CO>
<xsl:value-of select="Cost" />
</CO>
</xsl:for-each>
</EE>
</xsl:template>
</xsl:stylesheet>
The result
<?xml version="1.0" encoding="UTF-8"?>
<EES xmlns:xs="http://www.w3.org/2001/XMLSchema">
<EE>
<EID>E00001</EID>
<FULNAME>John Doe</FULNAME>
<LNAME>Doe</LNAME>
<FNAME>John</FNAME>
<CGR>Plan A</CGR>
<PFRMDT>2015-04-01-08:00</PFRMDT>
<BDT>2015-03-22-08:00 2015-02-03-08:00 2013-02-03-08:00</BDT>
<FLAG>N N N</FLAG>
<ADJBGNDT>"</ADJBGNDT>
<EDATE>"</EDATE>
<CO>6000 4000 3000</CO>
<CGR>Plan B</CGR>
<PFRMDT>2015-04-01-08:00</PFRMDT>
<BDT>2014-12-03-08:00 2014-10-03-08:00</BDT>
<FLAG>N N</FLAG>
<ADJBGNDT>"</ADJBGNDT>
<EDATE>"</EDATE>
<CO>12000 1000</CO>
</EE>
<EE>
<EID>E00002</EID>
<FULNAME>John Doe</FULNAME>
<LNAME>Test</LNAME>
<FNAME>Jane</FNAME>
<CGR>Plan D</CGR>
<PFRMDT>2015-01-01-08:00</PFRMDT>
<BDT>2015-05-22-08:00 2014-03-01-08:00</BDT>
<FLAG>Y N</FLAG>
<ADJBGNDT>"</ADJBGNDT>
<EDATE>"</EDATE>
<CO>12000 9000</CO>
<CGR>Plan C</CGR>
<PFRMDT>2015-01-01-08:00</PFRMDT>
<BDT>2014-12-03-08:00 2013-01-03-08:00</BDT>
<FLAG>N N</FLAG>
<ADJBGNDT>"</ADJBGNDT>
<EDATE>"</EDATE>
<CO>3000 3000</CO>
</EE>
</EES>
If you look at John Doe's BDT node, there are 2 dates. These are 2 nodes for the sample plan are getting added to the same node despite looping through the current group.
WHat is causing this? And what should be done to remedy this? I will have to use variables as there is more manulations I will have to do. But that is for another day.
Thanks for providng me some insight.
Inside of your bework variable you create a berow element for each Transaction group but then you use <xsl:for-each select="current-group()"> to output a begin-date for each Transaction in that group, without structuring or wrapping them further. With your input that means that berow element can contain two or three begin-date elements.
Then you have <xsl:for-each select="$bework/berow"> and inside
<BDT>
<xsl:value-of select="begin-date" />
</BDT>
which will select and output the string value of the two or three begin-date elements.
I am not sure which value you want to output for BDT, you could use e.g. <xsl:value-of select="begin-date[1]"/> or <xsl:value-of select="begin-date[last()]"/> to output only the string value of the first or last element created earlier.
Perhaps you just need to change:
<BDT>
<xsl:value-of select="begin-date" />
</BDT>
to:
<BDT>
<xsl:copy-of select="begin-date" />
</BDT>
In XSLT 2.0, xsl:value-of will generate a single text node, concatenating the values of all matching nodes, separated by a space (or another separator, if specified).
Additional explanation:
WHat is causing this?
The reason why your nodes are getting merged into a single text node is that you are using xsl:value-of when you try to fetch them from the $bework variable in order to write them into the output tree.
Consider the following simplified example:
XML
<root>
<item>
<category>A</category>
<amount>1000</amount>
</item>
<item>
<category>A</category>
<amount>500</amount>
</item>
<item>
<category>A</category>
<amount>250</amount>
</item>
<item>
<category>B</category>
<amount>600</amount>
</item>
<item>
<category>B</category>
<amount>300</amount>
</item>
</root>
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/root">
<xsl:variable name="groups">
<xsl:for-each-group select="item" group-by="category">
<group category="{current-grouping-key()}">
<xsl:for-each select="current-group()">
<amount>
<xsl:value-of select="amount"/>
</amount>
</xsl:for-each>
</group>
</xsl:for-each-group>
</xsl:variable>
<output>
<xsl:for-each select="$groups/group">
<group category="{#category}">
<copy-of-amount>
<xsl:copy-of select="amount"/>
</copy-of-amount>
<for-each-amount>
<xsl:for-each select="amount">
<new-node value="{.}"/>
</xsl:for-each>
</for-each-amount>
<sum-of-amount>
<xsl:value-of select="sum(amount)"/>
</sum-of-amount>
<value-of-amount>
<xsl:value-of select="amount"/>
</value-of-amount>
</group>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
Result
<?xml version="1.0" encoding="UTF-8"?>
<output>
<group category="A">
<copy-of-amount>
<amount>1000</amount>
<amount>500</amount>
<amount>250</amount>
</copy-of-amount>
<for-each-amount>
<new-node value="1000"/>
<new-node value="500"/>
<new-node value="250"/>
</for-each-amount>
<sum-of-amount>1750</sum-of-amount>
<value-of-amount>1000 500 250</value-of-amount>
</group>
<group category="B">
<copy-of-amount>
<amount>600</amount>
<amount>300</amount>
</copy-of-amount>
<for-each-amount>
<new-node value="600"/>
<new-node value="300"/>
</for-each-amount>
<sum-of-amount>900</sum-of-amount>
<value-of-amount>600 300</value-of-amount>
</group>
</output>
As you can see, inside the $myVar variable, each group contains 2-3 distinct amount nodes. You can copy them, sum them or create something for each one of them. However, when you do:
<xsl:value-of select="amount"/>
you are addressing all the amount nodes in the current group, and you will get a result that incorporates them all, same as:
<xsl:value-of select="sum(amount)"/>
returns a result based on all the amount nodes being addressed.
And what should be done to remedy this?
We won't know that until you tell us what is the actual result you want to get. In the comments below you said that:
the final result is really the total cost per employee.
If so, the example above shows how to get it.

XSL Copy nodes without xmlns

I have a specific problem. I have to transform an XML structure to other, where the base XSD is same, different only the namespace definition. The first part is simple, because here I have to use field-mapping. The second part is the simple copy. And here is the problem. The copied "main" node contains the original xmlns attribute. I need to remove this "attribute".
The base xml:
<?xml version="1.0" encoding="UTF-8"?>
<S2SCTIcf:SCTIcfBlkCredTrf xmlns:S2SCTIcf="urn:S2SCTIcf:xsd:$SCTIcfBlkCredTrf"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:S2SCTIcf:xsd:$SCTIcfBlkCredTrf SCTIcfBlkCredTrf.xsd">
<S2SCTIcf:SndgInst>XXXXXXX0</S2SCTIcf:SndgInst>
<S2SCTIcf:RcvgInst>YYYYYYY0</S2SCTIcf:RcvgInst>
<S2SCTIcf:FileRef>2013111200800546</S2SCTIcf:FileRef>
<S2SCTIcf:SrvcId>SCT</S2SCTIcf:SrvcId>
<S2SCTIcf:TstCode>T</S2SCTIcf:TstCode>
<S2SCTIcf:FType>ICF</S2SCTIcf:FType>
<S2SCTIcf:FDtTm>2013-11-12T16:26:31</S2SCTIcf:FDtTm>
<S2SCTIcf:NumCTBlk>1</S2SCTIcf:NumCTBlk>
<S2SCTIcf:NumPCRBlk>0</S2SCTIcf:NumPCRBlk>
<S2SCTIcf:NumRFRBlk>0</S2SCTIcf:NumRFRBlk>
<S2SCTIcf:NumROIBlk>0</S2SCTIcf:NumROIBlk>
<S2SCTIcf:FIToFICstmrCdtTrf xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02">
<GrpHdr>
<MsgId>xxddccxxaaa</MsgId>
<CreDtTm>2013-11-12T16:26:31</CreDtTm>
<NbOfTxs>1</NbOfTxs>
<TtlIntrBkSttlmAmt Ccy="EUR">469.12</TtlIntrBkSttlmAmt>
<IntrBkSttlmDt>2013-11-13</IntrBkSttlmDt>
<SttlmInf>
<SttlmMtd>CLRG</SttlmMtd>
<ClrSys>
<Prtry>ST2</Prtry>
</ClrSys>
</SttlmInf>
<InstgAgt>
<FinInstnId>
<BIC>XXXXXXX0</BIC>
</FinInstnId>
</InstgAgt>
</GrpHdr>
<CdtTrfTxInf>
<PmtId>
<EndToEndId>1114405599,1114382976</EndToEndId>
<TxId>F3232323232</TxId>
</PmtId>
<PmtTpInf>
<SvcLvl>
<Cd>SEPA</Cd>
</SvcLvl>
</PmtTpInf>
<IntrBkSttlmAmt Ccy="EUR">469.12</IntrBkSttlmAmt>
<ChrgBr>SLEV</ChrgBr>
<Dbtr>
<Nm>ddffrrddsaasas</Nm>
<PstlAdr>
<Ctry>HU</Ctry>
<AdrLine>dssdsdsdsdsdaas</AdrLine>
</PstlAdr>
</Dbtr>
<DbtrAcct>
<Id>
<IBAN>HU26XXXXXXXXXXXXXX</IBAN>
</Id>
</DbtrAcct>
<DbtrAgt>
<FinInstnId>
<BIC>CCCCHUH0</BIC>
</FinInstnId>
</DbtrAgt>
<CdtrAgt>
<FinInstnId>
<BIC>CVCVCVCVCVC</BIC>
</FinInstnId>
</CdtrAgt>
<Cdtr>
<Nm>XXXXX</Nm>
<PstlAdr>
<Ctry>DE</Ctry>
</PstlAdr>
</Cdtr>
<CdtrAcct>
<Id>
<IBAN>DE12vvvvvvvhghhg</IBAN>
</Id>
</CdtrAcct>
<RmtInf>
<Ustrd>0000000000,0000000000 </Ustrd>
</RmtInf>
</CdtTrfTxInf>
</S2SCTIcf:FIToFICstmrCdtTrf>
</S2SCTIcf:SCTIcfBlkCredTrf>
The xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:ns0="urn:S2SCTIcf:xsd:$SCTIcfBlkCredTrf"
xmlns:sw8="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02"
xmlns:S2SCTScf="urn:S2SCTScf:xsd:$SCTScfBlkCredTrf" exclude-result-prefixes="xs ns0 ">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="var1_SCTIcfBlkCredTrf" select="ns0:SCTIcfBlkCredTrf"/>
<S2SCTScf:SCTScfBlkCredTrf
xsi:schemaLocation="urn:S2SCTScf:xsd:$SCTScfBlkCredTrf SCTScfBlkCredTrf.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:S2SCTScf="urn:S2SCTScf:xsd:$SCTScfBlkCredTrf">
<xsl:for-each select="$var1_SCTIcfBlkCredTrf">
<S2SCTScf:SndgInst>
<xsl:value-of select="string(ns0:RcvgInst)"/>
</S2SCTScf:SndgInst>
</xsl:for-each>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf">
<S2SCTScf:RcvgInst>
<xsl:value-of select="string(ns0:SndgInst)"/>
</S2SCTScf:RcvgInst>
</xsl:for-each>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf">
<S2SCTScf:SrvcId>
<xsl:value-of select="string(ns0:SrvcId)"/>
</S2SCTScf:SrvcId>
</xsl:for-each>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf">
<S2SCTScf:TstCode>
<xsl:value-of select="string(ns0:TstCode)"/>
</S2SCTScf:TstCode>
</xsl:for-each>
<S2SCTScf:FType>SCF</S2SCTScf:FType>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf">
<S2SCTScf:FileRef>
<xsl:value-of select="string(ns0:FileRef)"/>
</S2SCTScf:FileRef>
</xsl:for-each>
<S2SCTScf:RoutingInd>DIR</S2SCTScf:RoutingInd>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf">
<S2SCTScf:FileBusDt>
<xsl:value-of select="string(ns0:FDtTm)"/>
</S2SCTScf:FileBusDt>
</xsl:for-each>
<S2SCTScf:FIToFICstmrCdtTrf xmlns="urn:iso:std:iso:20022:tech:xsd:pacs.008.001.02">
<xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
<GrpHdr>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
<MsgId>
<xsl:value-of select="string(sw8:GrpHdr/sw8:MsgId)"/>
</MsgId>
</xsl:for-each>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
<CreDtTm>
<xsl:value-of select="string(sw8:GrpHdr/sw8:CreDtTm)"/>
</CreDtTm>
</xsl:for-each>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
<NbOfTxs>
<xsl:value-of select="string(sw8:GrpHdr/sw8:NbOfTxs)"/>
</NbOfTxs>
</xsl:for-each>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
<xsl:variable name="var2_TtlIntrBkSttlmAmt"
select="sw8:GrpHdr/sw8:TtlIntrBkSttlmAmt"/>
<TtlIntrBkSttlmAmt>
<xsl:attribute name="Ccy" namespace="">
<xsl:value-of select="string($var2_TtlIntrBkSttlmAmt/#Ccy)"/>
</xsl:attribute>
<xsl:value-of
select="string(number(string($var2_TtlIntrBkSttlmAmt)))"/>
</TtlIntrBkSttlmAmt>
</xsl:for-each>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
<IntrBkSttlmDt>
<xsl:value-of select="string(sw8:GrpHdr/sw8:IntrBkSttlmDt)"/>
</IntrBkSttlmDt>
</xsl:for-each>
<SttlmInf>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
<SttlmMtd>
<xsl:value-of
select="string(sw8:GrpHdr/sw8:SttlmInf/sw8:SttlmMtd)"/>
</SttlmMtd>
</xsl:for-each>
<ClrSys>
<xsl:for-each select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf">
<Prtry>
<xsl:value-of
select="string(sw8:GrpHdr/sw8:SttlmInf/sw8:ClrSys/sw8:Prtry)"
/>
</Prtry>
</xsl:for-each>
</ClrSys>
</SttlmInf>
<InstdAgt>
<FinInstnId>
<xsl:for-each
select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf/sw8:GrpHdr/sw8:InstgAgt">
<BIC>
<xsl:value-of select="string(sw8:FinInstnId/sw8:BIC)"/>
</BIC>
</xsl:for-each>
</FinInstnId>
</InstdAgt>
</GrpHdr>
<xsl:copy-of select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf/sw8:CdtTrfTxInf" />
</xsl:for-each>
</S2SCTScf:FIToFICstmrCdtTrf>
</S2SCTScf:SCTScfBlkCredTrf>
</xsl:template>
</xsl:stylesheet>
The wrong part of output:
...
</InstdAgt>
</GrpHdr>
<CdtTrfTxInf xmlns:S2SCTIcf="urn:S2SCTIcf:xsd:$SCTIcfBlkCredTrf">
<PmtId>
<EndToEndId>1114405599,1114382976</EndToEndId>
<TxId>F3232323232</TxId>
...
I don't want to get the xmlns:S2SCTIcf="urn:S2SCTIcf:xsd:$SCTIcfBlkCredTrf" attribute this line.
Have someone any idea?
Thank you!
Feri
Your issue is that
<xsl:copy-of select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf/sw8:CdtTrfTxInf" />
copies the node from the original tree including its "namespace nodes", i.e. the namespace declarations that were in scope at that point in the original document. When this node is serialized any of these namespace nodes that are not already in force at this point in the output document will be declared by the serializer.
If you were able to use XSLT 2.0 then you could try setting copy-namespaces="no" on the copy-of but that isn't an option in XSLT 1.0. So instead of using copy-of you need to use templates to copy that node (and all its descendants recursively) without including the namespace nodes. The simplest way I can think of to do this is to declare two additional templates
<xsl:template match="*" mode="copy">
<xsl:element name="{name()}" namespace="{namespace-uri()}">
<xsl:apply-templates select="#*|node()" mode="copy" />
</xsl:element>
</xsl:template>
<xsl:template match="#*|text()|comment()" mode="copy">
<xsl:copy/>
</xsl:template>
and then replace that copy-of with
<xsl:apply-templates mode="copy"
select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf/sw8:CdtTrfTxInf" />
The trick here is that xsl:element is creating a new element node that happens to have the same name and namespace as the original one, rather than copying the original node, so it doesn't copy the namespace nodes.
You can use a variant of the answer here to get what you want.
Basically, you would create a template to rebuild that element without any namespaces. So you would add the following two templates to your current XSLT:
<xsl:template match="*" mode="copy-no-namespaces">
<xsl:element name="{local-name()}">
<xsl:copy-of select="#*"/>
<xsl:apply-templates select="node()" mode="copy-no-namespaces"/>
</xsl:element>
</xsl:template>
<xsl:template match="comment()| processing-instruction()" mode="copy-no-namespaces">
<xsl:copy/>
</xsl:template>
And then update your copy-of to
<xsl:apply-templates select="$var1_SCTIcfBlkCredTrf/ns0:FIToFICstmrCdtTrf/sw8:CdtTrfTxInf" mode="copy-no-namespaces"/>

How to split a node value which has xml as string in xslt

We have a requirement where we are getting an XML payload in form of String for one node and we need to expand this XML and pass the XML node values to destination XSD columns.
For example Input XSD :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Transaction xmlns="http://xmlns.oracle.com/2012/SCEM">
<TRXKEY>0x0000013</TRXKEY>
<EVENTNAME>SalesOrder</EVENTNAME>
<ACCEPTEDQUANTITY>0</ACCEPTEDQUANTITY>
<ORDEREDQUANTITY>0</ORDEREDQUANTITY>
<SOLORGID>0</SOLORGID>
<LHORDERHOLDIDRELEASED>0</LHORDERHOLDIDRELEASED>
<ORDEREDQUANTITYUOM>0</ORDEREDQUANTITYUOM>
<UNITSELLINGPRICE>0</UNITSELLINGPRICE>
<ORDERTYPE><Val lang='AR'>OrderTypeARARARAR</Val>
<Val lang='KO'>OrderTypeKOKOKOKO</Val>
<Val lang='US'>OrderTypeUSUSUUS</Val>
</ORDERTYPE>
</Transaction>
Output XML
<Transaction1 xmlns="http://xmlns.oracle.com/2012/SCEM">
<TRXKEY>0x0000013</TRXKEY>
<EVENTNAME>SalesOrder</EVENTNAME>
<ACCEPTEDQUANTITY>0</ACCEPTEDQUANTITY>
<ORDEREDQUANTITY>0</ORDEREDQUANTITY>
<SOLORGID>0</SOLORGID>
<LHORDERHOLDIDRELEASED>0</LHORDERHOLDIDRELEASED>
<ORDEREDQUANTITYUOM>0</ORDEREDQUANTITYUOM>
<UNITSELLINGPRICE>0</UNITSELLINGPRICE>
<ORDERTYPE_AR>OrderTypeARARARAR</ORDERTYPE_AR>
<ORDERTYPE_US>OrderTypeUSUSUUS</ORDERTYPE_US>
<ORDERTYPE_KO>OrderTypeKOKOKOKO</ORDERTYPE_KO>
</Transaction>
We need to loop through the ORDERTYPE node XML string. Depending on the 'Val lang=' value we need to pass this node value to output XSD ORDERTYPE_$lang value column.
How can I loop through this XML string for these 2 different values and pass it to the corresponding output XML column?
I was thinking of using split but it is not helping much.
Thanks Martin,
I have come up with below code which resolved my issue.
<xsl:stylesheet version="1.0"
xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/"
xmlns:xp20="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.Xpath20"
xmlns:mhdr="http://www.oracle.com/XSL/Transform/java/oracle.tip.mediator.service.common.functions.MediatorExtnFunction"
xmlns:bpel="http://docs.oasis-open.org/wsbpel/2.0/process/executable"
xmlns:oraext="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.ExtFunc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dvm="http://www.oracle.com/XSL/Transform/java/oracle.tip.dvm.LookupValue"
xmlns:hwf="http://xmlns.oracle.com/bpel/workflow/xpath"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:med="http://schemas.oracle.com/mediator/xpath"
xmlns:ids="http://xmlns.oracle.com/bpel/services/IdentityService/xpath"
xmlns:bpm="http://xmlns.oracle.com/bpmn20/extensions"
xmlns:client="http://xmlns.oracle.com/KeyStore/emsProjXslt/BPELProcess1"
xmlns:xdk="http://schemas.oracle.com/bpel/extension/xpath/function/xdk"
xmlns:xref="http://www.oracle.com/XSL/Transform/java/oracle.tip.xref.xpath.XRefXPathFunctions"
xmlns:ns2="http://xmlns.oracle.com/2012/SCEM"
xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:ora="http://schemas.oracle.com/xpath/extension"
xmlns:socket="http://www.oracle.com/XSL/Transform/java/oracle.tip.adapter.socket.ProtocolTranslator"
xmlns:ldap="http://schemas.oracle.com/xpath/extension/ldap"
exclude-result-prefixes="xsi xsl client ns2 plnk xsd wsdl bpws xp20 mhdr bpel oraext dvm hwf med ids bpm xdk xref ora socket ldap">
<xsl:template match="/">
<ns2:Transaction>
<ns2:TRXKEY>
<xsl:value-of select="/ns2:Transaction/ns2:TRXKEY"/>
</ns2:TRXKEY>
<xsl:call-template name="for.loop.Parameters">
<xsl:with-param name="sourceNodes"
select='substring-after(/ns2:Transaction/ns2:ORDERTYPE,"Val lang=")'/>
</xsl:call-template>
</ns2:Transaction>
</xsl:template>
<xsl:template name="for.loop.Parameters">
<xsl:param name="sourceNodes"/>
<xsl:variable name="temp">
<xsl:choose>
<xsl:when test="string-length($sourceNodes) > '0'">
<xsl:value-of select="substring-before($sourceNodes,'</Val>')"/>
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:variable name="Expression" select="substring-after($temp, '>')"/>
<xsl:variable name="Expression1" select="substring-before($temp, '>')"/>
<xsl:if test="contains($Expression1,'AR')">
<ns2:ORDERTYPE_AR>
<xsl:value-of select="$Expression"/>
</ns2:ORDERTYPE_AR>
</xsl:if>
<xsl:if test="contains($Expression,'US')">
<ns2:ORDERTYPE_US>
<xsl:value-of select="$Expression"/>
</ns2:ORDERTYPE_US>
</xsl:if>
<xsl:if test="contains($Expression,'KO')">
<ns2:ORDERTYPE_KO>
<xsl:value-of select="$Expression"/>
</ns2:ORDERTYPE_KO>
</xsl:if>
<xsl:variable name="test">
<xsl:value-of select="substring-after($sourceNodes,'/Val>')"/>
</xsl:variable>
<xsl:if test="string-length($test) > 1 ">
<xsl:call-template name="for.loop.Parameters">
<xsl:with-param name="sourceNodes">
<xsl:value-of select='substring-after($test,"Val lang=")'/>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

Merge functionality of two xsl files into a single file (continued.....)

This is in continuation of my question:
Merge functionality of two xsl files into a single file (not a xsl import or include issue)
I have to merge the solution (xsl) of above question to below xsl:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="/">
<Declaration>
<Message>
<Meduim>
<xsl:value-of select="/Declaration/Message/Meduim"/>
</Meduim>
<MessageIdentifier>
<xsl:value-of select="/Declaration/Message/MessageIdentifier"/>
</MessageIdentifier>
<ControlingAgencyCode>
<xsl:value-of select="/Declaration/Message/ControlingAgencyCode"/>
</ControlingAgencyCode>
<AssociationAssignedCode>
<xsl:value-of select="/Declaration/Message/AssociationAssignedCode"/>
</AssociationAssignedCode>
<CommonAccessReference>
<xsl:value-of select="/Declaration/Message/CommonAccessReference"/>
</CommonAccessReference>
</Message>
<BeginingOfMessage>
<MessageCode>
<xsl:value-of select="/Declaration/BeginingOfMessage/MessageCode"/>
</MessageCode>
<DeclarationCurrency>
<xsl:value-of select="/Declaration/BeginingOfMessage/DeclarationCurrency"/>
</DeclarationCurrency>
<MessageFunction>
<xsl:value-of select="/Declaration/BeginingOfMessage/MessageFunction"/>
</MessageFunction>
</BeginingOfMessage>
<Header>
<ProcessingInformation>
<xsl:for-each select="/Declaration/Header/ProcessingInformation/ProcessingInstructions">
<ProcessingInstructions>
<xsl:value-of select="."/>
</ProcessingInstructions>
</xsl:for-each>
</ProcessingInformation>
<xsl:for-each select="/Declaration/Header/Seal">
<Seal>
<SealID>
<xsl:value-of select="SealID"/>
</SealID>
<SealLanguage>
<xsl:value-of select="SealLanguage"/>
</SealLanguage>
</Seal>
</xsl:for-each>
<xsl:choose>
<xsl:when test='/Declaration/Header/DeclarantsReference = ""'>
<DeclarantsReference>
<xsl:text disable-output-escaping="no">A</xsl:text>
</DeclarantsReference>
</xsl:when>
<xsl:otherwise>
<DeclarantsReference>
<xsl:value-of select="/Declaration/Header/DeclarantsReference"/>
</DeclarantsReference>
</xsl:otherwise>
</xsl:choose>
<xsl:for-each select="/Declaration/Header/Items">
<Items>
<CustomsStatusOfGoods>
<CPC>
<xsl:value-of select="CustomsStatusOfGoods/CPC"/>
</CPC>
<CommodityCode>
<xsl:value-of select="CustomsStatusOfGoods/CommodityCode"/>
</CommodityCode>
<ECSuplementaryMeasureCode1>
<xsl:value-of select="CustomsStatusOfGoods/ECSuplementaryMeasureCode1"/>
</ECSuplementaryMeasureCode1>
<ECSuplementaryMeasureCode2>
<xsl:value-of select="CustomsStatusOfGoods/ECSuplementaryMeasureCode2"/>
</ECSuplementaryMeasureCode2>
<PreferenceCode>
<xsl:value-of select="CustomsStatusOfGoods/PreferenceCode"/>
</PreferenceCode>
</CustomsStatusOfGoods>
<xsl:for-each select="ItemAI">
<ItemAI>
<AICode>
<xsl:value-of select="AICode"/>
</AICode>
<AIStatement>
<xsl:value-of select="AIStatement"/>
</AIStatement>
<AILanguage>
<xsl:value-of select="AILanguage"/>
</AILanguage>
</ItemAI>
</xsl:for-each>
<Locations>
<CountryOfOriginCode>
<xsl:value-of select="Locations/CountryOfOriginCode"/>
</CountryOfOriginCode>
<xsl:for-each select="Locations/ItemCountryonRouteCode">
<ItemCountryonRouteCode>
<xsl:value-of select="."/>
</ItemCountryonRouteCode>
</xsl:for-each>
<ItemDispatchCountry>
<xsl:value-of select="Locations/ItemDispatchCountry"/>
</ItemDispatchCountry>
<ItemDestinationCountry>
<xsl:value-of select="Locations/ItemDestinationCountry"/>
</ItemDestinationCountry>
</Locations>
<Measurements>
<GrossMass>
<xsl:value-of select="Measurements/GrossMass"/>
</GrossMass>
<NetMass>
<xsl:value-of select="Measurements/NetMass"/>
</NetMass>
<SupplementaryUnits>
<xsl:value-of select="Measurements/SupplementaryUnits"/>
</SupplementaryUnits>
<ThirdQuantity>
<xsl:value-of select="Measurements/ThirdQuantity"/>
</ThirdQuantity>
</Measurements>
<xsl:for-each select="Package">
<Package>
<PackageNumber>
<xsl:value-of select="PackageNumber"/>
</PackageNumber>
<PackageKind>
<xsl:value-of select="PackageKind"/>
</PackageKind>
<PackageMarks>
<xsl:value-of select="PackageMarks"/>
</PackageMarks>
<PackageLanguage>
<xsl:value-of select="PackageLanguage"/>
</PackageLanguage>
</Package>
</xsl:for-each>
<PriceValue>
<ItemStatisticalValue>
<xsl:value-of select="PriceValue/ItemStatisticalValue"/>
</ItemStatisticalValue>
<ItemPrice>
<xsl:value-of select="PriceValue/ItemPrice"/>
</ItemPrice>
</PriceValue>
<ItemReferences>
<xsl:for-each select="ItemReferences/ContainerID">
<ContainerID>
<xsl:value-of select="."/>
</ContainerID>
</xsl:for-each>
<QuotaNo>
<xsl:value-of select="ItemReferences/QuotaNo"/>
</QuotaNo>
<UNDangerousGoodsCode>
<xsl:value-of select="ItemReferences/UNDangerousGoodsCode"/>
</UNDangerousGoodsCode>
</ItemReferences>
<GoodsDescription>
<GoodsDescription>
<xsl:value-of select="GoodsDescription/GoodsDescription"/>
</GoodsDescription>
<GoodsDescriptionLanguage>
<xsl:value-of select="GoodsDescription/GoodsDescriptionLanguage"/>
</GoodsDescriptionLanguage>
</GoodsDescription>
<Documents>
<xsl:for-each select="Documents/PreviousDocument">
<PreviousDocument>
<PreviousDocumentKind>
<xsl:value-of select="PreviousDocumentKind"/>
</PreviousDocumentKind>
<PreviousDocumentIdentifier>
<xsl:value-of select="PreviousDocumentIdentifier"/>
</PreviousDocumentIdentifier>
<PreviousDocumentType>
<xsl:value-of select="PreviousDocumentType"/>
</PreviousDocumentType>
<PreviousDocumentLanguage>
<xsl:value-of select="PreviousDocumentLanguage"/>
</PreviousDocumentLanguage>
</PreviousDocument>
</xsl:for-each>
<xsl:for-each select="Documents/ItemDocument">
<ItemDocument>
<DocumentCode>
<xsl:value-of select="DocumentCode"/>
</DocumentCode>
<DocumentPart>
<xsl:value-of select="DocumentPart"/>
</DocumentPart>
<DocumentQuantity>
<xsl:value-of select="DocumentQuantity"/>
</DocumentQuantity>
<DocumentReason>
<xsl:value-of select="DocumentReason"/>
</DocumentReason>
<DocumentReference>
<xsl:value-of select="DocumentReference"/>
</DocumentReference>
<DocumentStatus>
<xsl:value-of select="DocumentStatus"/>
</DocumentStatus>
<DocumentLanguage>
<xsl:value-of select="DocumentLanguage"/>
</DocumentLanguage>
</ItemDocument>
</xsl:for-each>
</Documents>
<Valuation>
<ValuationMethodCode>
<xsl:value-of select="Valuation/ValuationMethodCode"/>
</ValuationMethodCode>
<ItemValuationAdjustmentCode>
<xsl:value-of select="Valuation/ItemValuationAdjustmentCode"/>
</ItemValuationAdjustmentCode>
<ItemValuationAdjustmentPercentage>
<xsl:value-of select="Valuation/ItemValuationAdjustmentPercentage"/>
</ItemValuationAdjustmentPercentage>
</Valuation>
<ItemTransportChargeMOP>
<xsl:value-of select="ItemTransportChargeMOP"/>
</ItemTransportChargeMOP>
<xsl:for-each select="ItemProcessingInstructions">
<ItemProcessingInstructions>
<xsl:value-of select="."/>
</ItemProcessingInstructions>
</xsl:for-each>
</Items>
</xsl:for-each>
<NumberOfPackages>
<xsl:value-of select="/Declaration/Header/NumberOfPackages"/>
</NumberOfPackages>
</Header>
</Declaration>
</xsl:template>
</xsl:stylesheet>
so for source xml
<Declaration>
<Message>
<Meduim>#+#</Meduim>
<MessageIdentifier>AA</MessageIdentifier>
<CommonAccessReference></CommonAccessReference>
</Message>
<BeginingOfMessage>
<MessageCode>ISD</MessageCode>
<DeclarationCurrency></DeclarationCurrency>
<MessageFunction>5</MessageFunction>
</BeginingOfMessage>
</Declaration>
the final output is
<Declaration>
<Message>
<Meduim></Meduim>
<MessageIdentifier>AA</MessageIdentifier>
</Message>
<BeginingOfMessage>
<MessageCode>ISD</MessageCode>
<MessageFunction>5</MessageFunction>
</BeginingOfMessage>
</Declaration>
I. Performing a chain of transformations is used quite often in XSLT applications, though doing this entirely in XSLT 1.0 requires the use of the vendor-specific xxx:node-set() function. In XSLT 2.0 no such extension is needed as the infamous RTF datatype is eliminated there.
Here is an example (too-simple to be meaningful, but illustrating completely how this is done):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="vrtfPass1">
<xsl:apply-templates select="/*/*"/>
</xsl:variable>
<xsl:variable name="vPass1"
select="ext:node-set($vrtfPass1)"/>
<xsl:apply-templates mode="pass2"
select="$vPass1/*"/>
</xsl:template>
<xsl:template match="num[. mod 2 = 1]">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="num" mode="pass2">
<xsl:copy>
<xsl:value-of select=". *2"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the following XML document:
<nums>
<num>01</num>
<num>02</num>
<num>03</num>
<num>04</num>
<num>05</num>
<num>06</num>
<num>07</num>
<num>08</num>
<num>09</num>
<num>10</num>
</nums>
the wanted, correct result is produced:
<num>2</num>
<num>6</num>
<num>10</num>
<num>14</num>
<num>18</num>
Explanation:
In the first step the XML document is transformed and the result is defined as the value of the variable $vrtfPass1. This copies only the num elements that have odd value (not even).
The $vrtfPass1 variable, being of type RTF, is not directly usable for XPath expressions so we convert it to a normal tree, using the EXSLT (implemented by most XSLT 1.0 processors) function ext:node-set and defining another variable -- $vPass1 whose value is this tree.
We now perform the second transformation in our chain of transformations -- on the result of the first transformation, that is kept as the value of the variable $vPass1. Not to mess with the first-pass template, we specify that the new processing should be in a named mode, called "pass2". In this mode the value of any num element is multiplied by two.
See also the answer of Michael Kay to your first question, which also explained this general technique.
II. XSLT 2.0 solution (no RTFs):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="vPass1" >
<xsl:apply-templates select="/*/*"/>
</xsl:variable>
<xsl:apply-templates mode="pass2"
select="$vPass1/*"/>
</xsl:template>
<xsl:template match="num[. mod 2 = 1]">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="num" mode="pass2">
<xsl:copy>
<xsl:value-of select=". *2"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
III. Using the compose() and compose-flist() functions/templates of FXSL
The FXSL library provides two convenient functions/template that support easy chaining of transformations. The former composes two functions/transformations while the latter composes all functions/transformations that are provided in a sequence.
Here is a simple, complete code example:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:f="http://fxsl.sf.net/"
xmlns:myFun1="f:myFun1"
xmlns:myFun2="f:myFun2"
xmlns:ext="http://exslt.org/common"
exclude-result-prefixes="xsl f ext myFun1 myFun2"
>
<xsl:import href="compose.xsl"/>
<xsl:import href="compose-flist.xsl"/>
<!-- to be applied on any xml source -->
<xsl:output method="text"/>
<myFun1:myFun1/>
<myFun2:myFun2/>
<xsl:template match="/">
<xsl:variable name="vFun1" select="document('')/*/myFun1:*[1]"/>
<xsl:variable name="vFun2" select="document('')/*/myFun2:*[1]"/>
Compose:
(*3).(*2) 3 =
<xsl:call-template name="compose">
<xsl:with-param name="pFun1" select="$vFun1"/>
<xsl:with-param name="pFun2" select="$vFun2"/>
<xsl:with-param name="pArg1" select="3"/>
</xsl:call-template>
<xsl:variable name="vrtfParam">
<xsl:copy-of select="$vFun1"/>
<xsl:copy-of select="$vFun2"/>
<xsl:copy-of select="$vFun1"/>
</xsl:variable>
Multi Compose:
(*3).(*2).(*3) 2 =
<xsl:call-template name="compose-flist">
<xsl:with-param name="pFunList" select="ext:node-set($vrtfParam)/*"/>
<xsl:with-param name="pArg1" select="2"/>
</xsl:call-template>
</xsl:template>
<xsl:template match="myFun1:*" mode="f:FXSL">
<xsl:param name="pArg1"/>
<xsl:value-of select="3 * $pArg1"/>
</xsl:template>
<xsl:template match="myFun2:*" mode="f:FXSL">
<xsl:param name="pArg1"/>
<xsl:value-of select="2 * $pArg1"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on any XML document (not used), the wanted, correct results are produced:
Compose:
(*3).(*2) 3 =
18
Multi Compose:
(*3).(*2).(*3) 2 =
36
Pure XSLT 1.0 does not support chaining templates (nor stylesheets as a whole). You can either solve this program outside of XSLT by calling the second xslt template and passing it the output of the first manually, or you can use the fairly pervasive extension function node-set(). MSXML, .NET, EXSL and many other implementations support such a function. The namespace prefix for node-set varies depending on XSLT implementation, but the EXSL prefix is a good bet (and .NET, though undocumented, supports this).
To use node-set store the result of a template in an xsl:variable or xsl:param and do something like <xsl:apply-templates select="exsl:node-set($myvarname)"/>.
Finally, you can of course rewrite your two templates to provide the functionality of both in one pass - but in general, this isn't a trivial thing to do.
I don't understand the problem.
The solution I posted in your last question already works.
For this input:
<?xml version="1.0" encoding="UTF-8"?>
<Declaration>
<Message>
<Meduim>#+#</Meduim>
<MessageIdentifier>AA</MessageIdentifier>
<CommonAccessReference></CommonAccessReference>
</Message>
<BeginingOfMessage>
<MessageCode>ISD</MessageCode>
<DeclarationCurrency></DeclarationCurrency>
<MessageFunction>5</MessageFunction>
</BeginingOfMessage>
</Declaration>
Output will be:
<?xml version="1.0" encoding="UTF-8"?>
<Declaration>
<Message>
<Meduim/>
<MessageIdentifier>AA</MessageIdentifier>
</Message>
<BeginingOfMessage>
<MessageCode>ISD</MessageCode>
<MessageFunction>5</MessageFunction>
</BeginingOfMessage>
</Declaration>
You, in fact, don't need your original stylesheet, because basically you just copy the tree.