Skip to content Skip to sidebar Skip to footer

Xslt: Transform Nodes By Comparing Their Child Nodes

To start off, I'm aware of this SO question which is a bit different. I have an XML file which looks like this:

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:

  1. the contents of the corresponding PmtInf element, except CdtTrfTxInf ;

  2. a copy of all CdtTrfTxInf elements from all the members of the group.

XSLT 1.0

<xsl:stylesheetversion="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:outputmethod="xml"version="1.0"encoding="UTF-8"indent="yes"/><xsl:strip-spaceelements="*"/><xsl:keyname="pmt"match="ns0:pmt"use="." /><xsl:keyname="PmtInf"match="ns0:PmtInf"use="generate-id()" /><xsl:variablename="input"select="/" /><!-- identity transform --><xsl:templatematch="@*|node()"><xsl:copy><xsl:apply-templatesselect="@*|node()"/></xsl:copy></xsl:template><xsl:templatematch="ns0:CstmrCdtTrfInitn"><!-- first pass --><xsl:variablename="first-pass-rtf"><xsl:apply-templatesselect="ns0:PmtInf"mode="gen-key"/></xsl:variable><xsl:variablename="first-pass"select="exsl:node-set($first-pass-rtf)" /><!-- output --><xsl:copy><xsl:copy-ofselect="ns0:GrpHdr"/><!-- for each distinct pmt --><xsl:for-eachselect="$first-pass/ns0:pmt[count(. | key('pmt', .)[1]) = 1]"><xsl:variablename="id"select="@id" /><xsl:variablename="ids"select="key('pmt', .)/@id" /><PmtInf><!-- switch context back to XML input --><xsl:for-eachselect="$input"><xsl:copy-ofselect="key('PmtInf', $id)/*[not(self::ns0:CdtTrfTxInf)]"/><xsl:copy-ofselect="key('PmtInf', $ids)/ns0:CdtTrfTxInf"/></xsl:for-each></PmtInf></xsl:for-each></xsl:copy></xsl:template><xsl:templatematch="ns0:PmtInf"mode="gen-key"><pmtid="{generate-id()}"><xsl:apply-templatesselect="@*|*"mode="gen-key"/></pmt></xsl:template><xsl:templatematch="@*|node()"mode="gen-key"><xsl:text>[</xsl:text><xsl:value-ofselect="name()"/><xsl:text>:</xsl:text><xsl:value-ofselect="."/><xsl:text>]</xsl:text><xsl:apply-templatesselect="@*|*"mode="gen-key"/></xsl:template><xsl:templatematch="ns0:CdtTrfTxInf"mode="gen-key"/></xsl:stylesheet>

Post a Comment for "Xslt: Transform Nodes By Comparing Their Child Nodes"