XSLT: Transform Nodes By Comparing Their Child Nodes
Solution 1:
I hesitate whether to post this at all, because you seem to be a beginner at XSLT and this is a complex solution to a complex problem. It may take you quite some time to wrap your head around this.
How this works:
In the first pass, we generate a pmt
element for each PmtInf
element in your input XML, and populate it with a string that contains a name/value pair for each node (element or attribute) descendant of the current PmtInf
. In the given example, each such pmt
element would look similar to:
<pmt id="idp1696">[PmtInfId:asd][PmtMtd:TRF][BtchBookg:false][PmtTpInf:NORMtest][InstrPrty:NORM][SvcLvl:test][Prtry:test][ReqdExctnDt:date][Dbtr:somethingaddr 1][Nm:something][PstlAdr:addr 1][AdrLine:addr 1]</pmt>
In the next step we apply Muenchian grouping to the pmt
nodes generated in the first pass. For each distinct pmt
node, we create a PmtInf
element and populate it with:
the contents of the corresponding
PmtInf
element, exceptCdtTrfTxInf
;a copy of all
CdtTrfTxInf
elements from all the members of the group.
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03"
xmlns="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03"
xmlns:exsl="http://exslt.org/common"
exclude-result-prefixes="ns0"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="pmt" match="ns0:pmt" use="." />
<xsl:key name="PmtInf" match="ns0:PmtInf" use="generate-id()" />
<xsl:variable name="input" select="/" />
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns0:CstmrCdtTrfInitn">
<!-- first pass -->
<xsl:variable name="first-pass-rtf">
<xsl:apply-templates select="ns0:PmtInf" mode="gen-key"/>
</xsl:variable>
<xsl:variable name="first-pass" select="exsl:node-set($first-pass-rtf)" />
<!-- output -->
<xsl:copy>
<xsl:copy-of select="ns0:GrpHdr"/>
<!-- for each distinct pmt -->
<xsl:for-each select="$first-pass/ns0:pmt[count(. | key('pmt', .)[1]) = 1]">
<xsl:variable name="id" select="@id" />
<xsl:variable name="ids" select="key('pmt', .)/@id" />
<PmtInf>
<!-- switch context back to XML input -->
<xsl:for-each select="$input">
<xsl:copy-of select="key('PmtInf', $id)/*[not(self::ns0:CdtTrfTxInf)]"/>
<xsl:copy-of select="key('PmtInf', $ids)/ns0:CdtTrfTxInf"/>
</xsl:for-each>
</PmtInf>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="ns0:PmtInf" mode="gen-key">
<pmt id="{generate-id()}">
<xsl:apply-templates select="@*|*" mode="gen-key"/>
</pmt>
</xsl:template>
<xsl:template match="@*|node()" mode="gen-key">
<xsl:text>[</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>:</xsl:text>
<xsl:value-of select="."/>
<xsl:text>]</xsl:text>
<xsl:apply-templates select="@*|*" mode="gen-key"/>
</xsl:template>
<xsl:template match="ns0:CdtTrfTxInf" mode="gen-key"/>
</xsl:stylesheet>
Post a Comment for "XSLT: Transform Nodes By Comparing Their Child Nodes"