I am trying to apply grouping logic on below XML. It is bit tricky for me as it is referring both inside and outside elements from array and grouping is to be done on code which is form inside array. I have provided what I tried but it is ineffective as it is not giving me desired output. Please suggest how can I group this.
Expected output:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:object xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:array name="OPDetails">
<xsl:object>
<xsl:string name="CategoryCode">I</xsl:string>
<xsl:array name="points">
<xsl:object>
<xsl:string name="Id">514355801</xsl:string>
<xsl:string name="TypeCode">ABC</xsl:string>
<xsl:string name="CategoryDescription">INDIVIDUAL</xsl:string>
<xsl:string name="TypeDescription">POCKET</xsl:string>
</xsl:object>
</xsl:array>
<xsl:array name="points">
<xsl:object>
<xsl:string name="Id">514355801</xsl:string>
<xsl:string name="TypeCode">DEF</xsl:string>
<xsl:string name="CategoryDescription">INDIVIDUAL</xsl:string>
<xsl:string name="TypeDescription">BANK</xsl:string>
</xsl:object>
</xsl:array>
</xsl:object>
<xsl:object>
<xsl:string name="CategoryCode">F</xsl:string>
<xsl:array name="points">
<xsl:object>
<xsl:string name="Id">514355801</xsl:string>
<xsl:string name="TypeCode">ABC</xsl:string>
<xsl:string name="CategoryDescription">FAMILY</xsl:string>
<xsl:string name="TypeDescription">POCKET</xsl:string>
</xsl:object>
</xsl:array>
<xsl:array name="points">
<xsl:object>
<xsl:string name="Id">514355801</xsl:string>
<xsl:string name="TypeCode">DEF</xsl:string>
<xsl:string name="CategoryDescription">FAMILY</xsl:string>
<xsl:string name="TypeDescription">BANK</xsl:string>
</xsl:object>
</xsl:array>
</xsl:object>
</xsl:array>
</xsl:object>
Input:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:object xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:string name="Id">514355801</xsl:string>
<xsl:array name="Details">
<xsl:object>
<xsl:string name="CategoryCode">I</xsl:string>
<xsl:string name="CategoryDescription">INDIVIDUAL</xsl:string>
<xsl:string name="TypeCode">ABC</xsl:string>
<xsl:string name="TypeDescription">POCKET</xsl:string>
</xsl:object>
<xsl:object>
<xsl:string name="CategoryCode">I</xsl:string>
<xsl:string name="CategoryDescription">INDIVIDUAL</xsl:string>
<xsl:string name="TypeCode">DEF</xsl:string>
<xsl:string name="TypeDescription">BANK</xsl:string>
</xsl:object>
<xsl:object>
<xsl:string name="CategoryCode">F</xsl:string>
<xsl:string name="CategoryDescription">FAMILY</xsl:string>
<xsl:string name="TypeCode">ABC</xsl:string>
<xsl:string name="TypeDescription">POCKET</xsl:string>
</xsl:object>
<xsl:object>
<xsl:string name="CategoryCode">F</xsl:string>
<xsl:string name="CategoryDescription">FAMILY</xsl:string>
<xsl:string name="TypeCode">DEF</xsl:string>
<xsl:string name="TypeDescription">BANK</xsl:string>
</xsl:object>
</xsl:array>
</xsl:object>
what I tried - XSL
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:object>
<xsl:array name="OPDetails">
<xsl:for-each select="xsl:object/xsl:array[@name='Details']/xsl:object">
<xsl:object>
<xsl:string name="CategoryCode">
<xsl:value-of select="./xsl:string[@name='CategoryCode']" />
</xsl:string>
<xsl:array name="points">
<xsl:object>
<xsl:string name="ID">
<xsl:value-of select="./xsl:object/xsl:string[@name='Id']" />
</xsl:string>
<xsl:string name="TypeCode">
<xsl:value-of select="./xsl:string[@name='TypeCode']" />
</xsl:string>
<xsl:string name="CategoryDescription">
<xsl:value-of select="./xsl:string[@name='CategoryDescription']" />
</xsl:string>
<xsl:string name="TypeDescription">
<xsl:value-of select="./xsl:string[@name='TypeDescription']" />
</xsl:string>
</xsl:object>
</xsl:array>
</xsl:object>
</xsl:for-each>
</xsl:array>
</xsl:object>
</xsl:template>
</xsl:stylesheet>
I do not see any attempt to group in your stylesheet. If you're limited to XSLT 1.0. you should use the Muenchian method to group nodes. In your example, that would look something like:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:axsl="http://www.w3.org/1999/XSL/TransformAlias">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>
<xsl:key name="obj-by-cat" match="xsl:object" use="xsl:string[@name='CategoryCode']" />
<xsl:template match="/xsl:object">
<xsl:variable name="id" select="xsl:string[@name='Id']" />
<xsl:copy>
<axsl:array name="Details">
<!-- create a group for each distinct category -->
<xsl:for-each select="xsl:array/xsl:object[count(. | key('obj-by-cat', xsl:string[@name='CategoryCode'])[1]) = 1]">
<axsl:object>
<xsl:copy-of select="xsl:string[@name='CategoryCode']"/>
<!-- get items in current category -->
<xsl:for-each select="key('obj-by-cat', xsl:string[@name='CategoryCode'])">
<axsl:array name="points">
<xsl:copy>
<xsl:copy-of select="$id"/>
<xsl:copy-of select="xsl:string[@name='TypeCode']"/>
<xsl:copy-of select="xsl:string[@name='CategoryDescription']"/>
<xsl:copy-of select="xsl:string[@name='TypeDescription']"/>
</xsl:copy>
</axsl:array>
</xsl:for-each>
</axsl:object>
</xsl:for-each>
</axsl:array>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
For explanation of the namespace alias, read:
https://www.w3.org/TR/1999/REC-xslt-19991116/#literal-result-element
Note that the result may vary slightly according to the processor you use. Some processors will output literal result elements using the axsl
prefix. Since this prefix is bound to the same namespace as the xsl
prefix, the difference is purely cosmetic.