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

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>

Related

Which is the correct approach out of the two?

I'm having an XML and likes to retrieve and concatenate values
Below is the Sample XML from which we need to retrieve the values:
<?xml version="1.0" encoding="UTF-8"?>
<Document>
<docBody>
<employee>
<employeeNumber>595</employeeNumber>
</employee>
<employeeAddress>
<empAddress>1</empAddress>
<empAddress2>1</empAddress2>
</employeeAddress>
</docBody>
<Messages />
</Document>
Method1:
<xsl:template match="employee">
<xsl:variable name="empNbr">
<xsl:value-of select="employeeNumber"/>
</xsl:variable>
<xsl:variable name="empAddress">
<xsl:value-of select="../employeeDetails/employeeAddress"/>
</xsl:variable>
<xsl:variable name="empAddress2">
<xsl:value-of select="../employeeDetails/empAddress2"/>
</xsl:variable>
<xsl:value-of select="concat($empNbr,$empAddress,$empAddress2)"/>
</xsl:template>
Method2:
<xsl:template match="employee">
<xsl:value-of select="concat(<xsl:value-of select="employeeNumber"/>,
<xsl:value-of select="../employeeDetails/employeeAddress"/>,
<xsl:value-of select="../employeeDetails/empAddress2"/>)"/>
</xsl:template>
Thanks in advance.
It's usually better to write variable declarations like so
<xsl:variable name="empNbr" select="employeeNumber" />
This means empNbr now references the employeeNumber directly. By using xsl:value-of this effectively gets the text value of empNbr and assigns it to the variable.
Your second method is not valid XSLT. The expression you are looking for is this...
<xsl:value-of select="concat(employeeNumber, ../employeeDetails/employeeAddress, ../employeeDetails/empAddress2)" />
Or you could have three separate xsl:value-of statements.
<xsl:value-of select="employeeNumber"/>
<xsl:value-of select="../employeeDetails/employeeAddress"/>
<xsl:value-of select="../employeeDetails/empAddress2"/>

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>

How to Optimize XSLT for Referencing data in other XMLs

In an input XML file, along with Static Columns, columns expecting data from other files (reference)is also available.
But for each reference, the input xml has separate row with same ID or UID.
The output file has to have all references and relations in one row (based on the ID or UID)
I wrote the XSLT for this transformation also. This XSLT is faster when the row count is less (< 100 or < 200). But, as the count grows, the output xml generation taking long time (for count of 1000 rows, around 30 mins).
I am using
<xsl:for-each select="z:row/#ID[generate-id() = generate-id(key('UniqueID',.))]">
in the XSLT. Because for the same ID in each row of input xml, it has to check for multiple references (like section) and relations (like Child) and populate the same as columns
Input Raw XML File.
<xml xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:z="#RowsetSchema">
<rs:data>
<z:row UID="PARENT_001_1221AD_A878" GroupID="" GroupRel="" ID="37" Name="Outer Asset Details" RelProduct="Line1" RelUID="CHILD1_101_9899_9POOU99" RelName="CHILD1" RelType="Child" Size="22"/>
<z:row UID="PARENT_001_1221AD_A878" GroupID="" GroupRel="" ID="37" Name="Outer Asset Details" RelProduct="Line1" RelUID="CHILD2_201_5646546_9890PBS" RelName="CHILD1" RelType="Child" Size="22"/>
<z:row UID="PARENT_001_1221AD_A878" GroupID="" GroupRel="" ID="37" Name="Outer Asset Details" RelProduct="Line1" RelUID="SEC_999_99565_998AFSD" RelName="Hydraulic Section" RelType="Section" Size="22"/>
</rs:data>
Child.xml
<Child xsi:noNamespaceSchemaLocation="../XSD/Child.xsd" FILE="Child" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Row UID="CHILD1_101_9899_9POOU99">
<Name>CHILD1</Name>
<Description>This has details about the Hydraulic sections of the automobile</Description>
</Row>
<Row UID="CHILD2_201_5646546_9890PBS">
<Name>CHILD2</Name>
<Description>This has details about the manual sections of the automobile</Description>
</Row>
Section.xml
<Section xsi:noNamespaceSchemaLocation="../XSD/Section.xsd" FILE="Section" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Row UID="SEC_999_99565_998AFSD">
<Name>Hydraulic Section</Name>
<Description>This has details about the Sections in which the Hydraulic Systems are used.</Description>
</Row>
XSLT File
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema" exclude-result-prefixes="s dt z rs msxsl" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="UniqueID" match="z:row/#ID" use="."/>
<xsl:template match="/">
<Parent xsi:noNamespaceSchemaLocation="../XSD/Parent.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" FILE="Parent">
<xsl:for-each select="xml">
<xsl:apply-templates select="rs:data"/>
</xsl:for-each>
</Parent>
</xsl:template>
<xsl:template match="rs:data">
<xsl:for-each select="z:row/#ID[generate-id() = generate-id(key('UniqueID',.))]">
<xsl:variable name="FRId">
<xsl:value-of select="current()"/>
</xsl:variable>
<xsl:variable name="curNSet" select="//z:row[#ID=$FRId]"/>
<xsl:copy-of select="current()"/>
<Record>
<xsl:attribute name="UID"><xsl:value-of select="$curNSet/#UID"/></xsl:attribute>
<xsl:element name="Size">
<xsl:value-of select="$curNSet/#Size"/>
</xsl:element>
<xsl:element name="Child">
<xsl:apply-templates select="$curNSet[#RelType='Child']" mode="Relations">
<xsl:with-param name="RelType" select="'Child'"/>
<xsl:with-param name="DstFileName" select="'../Files/Child.xml'"/>
</xsl:apply-templates>
</xsl:element>
<xsl:element name="Section">
<xsl:apply-templates select="$curNSet[#RelType='Section']" mode="References">
<xsl:with-param name="RelType" select="'Section'"/>
<xsl:with-param name="DstFileName" select="'../Files/Section.xml'"/>
</xsl:apply-templates>
</xsl:element>
</Record>
</xsl:for-each>
</xsl:template>
<xsl:template match="z:row" mode="Relations">
<xsl:param name="RelType"/>
<xsl:param name="DstFileName"/>
<xsl:element name="{$RelType}">
<xsl:attribute name="DestinationKey"><xsl:value-of select="#RelUID"/></xsl:attribute>
<xsl:attribute name="RelFilePath"><xsl:value-of select="$DstFileName"/></xsl:attribute>
<xsl:attribute name="SequenceNumber"><xsl:value-of select="position()"/></xsl:attribute>
<xsl:value-of select="#RelName"/>
</xsl:element>
</xsl:template>
<xsl:template match="z:row" mode="References">
<xsl:param name="DstFileName"/>
<xsl:attribute name="DestinationKey"><xsl:value-of select="#RelUID"/></xsl:attribute>
<xsl:attribute name="RelFilePath"><xsl:value-of select="$DstFileName"/></xsl:attribute>
<xsl:attribute name="SequenceNumber"><xsl:value-of select="position()"/></xsl:attribute>
<xsl:value-of select="#RelName"/>
</xsl:template>
Output.xml
<Parent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../XSD/Parent.xsd" FILE="Parent" ID="37">
<Record UID="PARENT_001_1221AD_A878">
<Size>22</Size>
<Child>
<Child DestinationKey="CHILD1_101_9899_9POOU99" RelFilePath="../Files/Child.xml" SequenceNumber="1">CHILD1</Child>
<Child DestinationKey="CHILD2_201_5646546_9890PBS" RelFilePath="../Files/Child.xml" SequenceNumber="2">CHILD1</Child>
</Child>
<Section DestinationKey="SEC_999_99565_998AFSD" RelFilePath="../Files/Section.xml" SequenceNumber="1">Hydraulic Section</Section>
</Record>
Please help me in optimizing the XSLT, so that the output file is generated faster
Consider to use
<xsl:key name="UniqueID" match="z:row" use="#ID"/>
then
<xsl:for-each select="z:row/#ID[generate-id() = generate-id(key('UniqueID',.))]">
<xsl:variable name="FRId">
<xsl:value-of select="current()"/>
</xsl:variable>
<xsl:variable name="curNSet" select="//z:row[#ID=$FRId]"/>
can be replaced with
<xsl:for-each select="z:row[generate-id() = generate-id(key('UniqueID', #ID))]">
<xsl:variable name="FRId" select="#ID"/>
<xsl:variable name="curNSet" select="key('UniqueID', #ID"/>
I am not sure you need the variable FRId at all but defining it with a select attribute instead of a nested value-of is certainly consuming less resources.
To make
<xsl:apply-templates select="$curNSet[#RelType='Child']" mode="Relations">
more efficient define a key
<xsl:key name="rel" match="z:row" use="concat(#ID, '|', #RelType)"/>
then use
<xsl:apply-templates select="key('rel', concat(#ID, '|', 'Child')" mode="Relations">
Then use the same approach for the other apply-templates.
All of the above is untested but should give you an idea.

XSLT: How to separate deliminated values into unique elements

I'm working in a database that doesn't really support subelements. To get around this, we've been using squiggly brackets }} in a string of values to indicate separations between subelements. When we export to xml, it looks something like this:
<geographicSubject>
<data>Mexico }} tgn }} 123456</data>
<data>Mexico City }} tgn }} 7891011</data>
<data>Main Street }} tgn }} 654321</data>
</geographicSubject>
My question: how do I create our XSLT so that it splits the strings in <data> into separate uniquely named subelements like this:
<data>
<location>Mexico</location>
<source>tgn</source>
<id>123456</id>
</data>
The first }} indicates the start of "source", the second }} indicates the start of "id". Thanks to anyone willing to help!
Compose a tokenizer:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:e="http://localhost">
<e:e>location</e:e>
<e:e>source</e:e>
<e:e>id</e:e>
<xsl:variable name="vElement" select="document('')/*/e:*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="data/text()" name="tokenizer">
<xsl:param name="pString" select="string()"/>
<xsl:param name="pPosition" select="1"/>
<xsl:if test="$pString">
<xsl:element name="{$vElement[$pPosition]}">
<xsl:value-of
select="normalize-space(
substring-before(concat($pString,'}}'),'}}')
)"/>
</xsl:element>
<xsl:call-template name="tokenizer">
<xsl:with-param name="pString"
select="substring-after($pString,'}}')"/>
<xsl:with-param name="pPosition" select="$pPosition + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Output:
<geographicSubject>
<data>
<location>Mexico</location>
<source>tgn</source>
<id>123456</id>
</data>
<data>
<location>Mexico City</location>
<source>tgn</source>
<id>7891011</id>
</data>
<data>
<location>Main Street</location>
<source>tgn</source>
<id>654321</id>
</data>
</geographicSubject>