'Grouping by concatination of two fields in XSLT 1.0
I'm in big trouble with a task I should fulfill and tryed it for several days now. I would be very grateful to anyone who can help with the solution.
Problem
I need to group values together within a XSL transformation (XSLT 1.0). Of course I searched the forum and web so I found that I have to do it with muenchian grouping. I just can't get managed to get it running on my own.
Filling the field YCSSTKLID with grouped values:
- YCSSTKLID need to be filled with a concatenation out of "ESN" + "GRAPHIC_NAME" (e.g '123#1' for ESN '123' and GRAPHIC_NAME '1.png'
- Every combination of ESN + GRAPHIC_NAME must only be contained a single time, so the duplicates need to be removed
- A ESN can have multiple associated GRAPHIC_NAMES
- A GRAPHIC_NAME can belong to multiple ESN
Simplified Source
<?xml version="1.0" encoding="utf-8"?>
<ns:MT_FlatFile_Lists_Cu xmlns:ns="urn:las:pp:ss1:tar">
<Cu_Records>
<Record>
<ESN>123</ESN>
<GRAPHIC_NAME>1.png</GRAPHIC_NAME>
<LEVEL_NO>1</LEVEL_NO>
<CALLOUT></CALLOUT>
</Record>
<Record>
<ESN>123</ESN>
<GRAPHIC_NAME>2.png</GRAPHIC_NAME>
<LEVEL_NO>2</LEVEL_NO>
<CALLOUT></CALLOUT>
</Record>
<Record>
<ESN>123</ESN>
<GRAPHIC_NAME>2.png</GRAPHIC_NAME>
<LEVEL_NO>3</LEVEL_NO>
<CALLOUT>3</CALLOUT>
</Record>
<Record>
<ESN>456</ESN>
<GRAPHIC_NAME>2.png</GRAPHIC_NAME>
<LEVEL_NO>1</LEVEL_NO>
<CALLOUT></CALLOUT>
</Record>
<Record>
<ESN>456</ESN>
<GRAPHIC_NAME>2.png</GRAPHIC_NAME>
<LEVEL_NO>2</LEVEL_NO>
<CALLOUT>17</CALLOUT>
</Record>
<Record>
<ESN>456</ESN>
<GRAPHIC_NAME>3.png</GRAPHIC_NAME>
<LEVEL_NO>2</LEVEL_NO>
<CALLOUT>18</CALLOUT>
</Record>
</Cu_Records>
</ns:MT_FlatFile_Lists_Cu>
Desired Output
<?xml version="1.0" encoding="UTF-8"?>
<YCSMKO01>
<IDOC BEGIN="1">
<EDI_DC40 SEGMENT="1">
<SNDPOR></SNDPOR>
<SNDPRT></SNDPRT>
<SNDPRN></SNDPRN>
<SNDLAD></SNDLAD>
</EDI_DC40>
<YCSMOTOR_KONF01 SEGMENT="1">
<YCSMOTOR_KONF02 SEGMENT="1">
<YCSSTKLID>123#1</YCSSTKLID>
</YCSMOTOR_KONF02>
<YCSMOTOR_KONF02 SEGMENT="1">
<YCSSTKLID>123#2</YCSSTKLID>
</YCSMOTOR_KONF02>
</YCSMOTOR_KONF01>
</IDOC>
</YCSMKO01>
<YCSMKO01>
<IDOC BEGIN="1">
<EDI_DC40 SEGMENT="1">
<SNDPOR></SNDPOR>
<SNDPRT></SNDPRT>
<SNDPRN></SNDPRN>
<SNDLAD></SNDLAD>
</EDI_DC40>
<YCSMOTOR_KONF01 SEGMENT="1">
<YCSMOTOR_KONF02 SEGMENT="1">
<YCSSTKLID>456#2</YCSSTKLID>
</YCSMOTOR_KONF02>
<YCSMOTOR_KONF02 SEGMENT="1">
<YCSSTKLID>456#3</YCSSTKLID>
</YCSMOTOR_KONF02>
</YCSMOTOR_KONF01>
</IDOC>
</YCSMKO01>
Reduced example XSL
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0" xmlns:xsltc="http://xml.apache.org/xalan/xsltc" xmlns:map="java.util.Map" xmlns:dyn="com.sap.aii.mapping.api.DynamicConfiguration" xmlns:key="com.sap.aii.mapping.api.DynamicConfigurationKey" xmlns:ns="urn:las:pp:ss1:tar" exclude-result-prefixes="xs ns xsl map key dyn xsltc">
<xsl:output indent="yes"/>
<xsl:key name="a" match="Record" use="ESN"/>
<xsl:key name="grouping" match="/ns:MT_FlatFile_Lists_Cu/Cu_Records/Record" use="concat(./ESN, ./GRAPHIC_NAME)"/>
<xsl:template match="/">
<xsl:apply-templates select="/ns:MT_FlatFile_Lists_Cu/Cu_Records/Record[generate-id(.) = generate-id(key('a', ESN))]" mode="head">
</xsl:apply-templates>
</xsl:template>
<!-- IDoc-Struktur -->
<xsl:template match="Record" mode="head">
<xsl:param name="pTime"/>
<xsl:variable name="esn" select="ESN"/>
<YCSMKO01>
<IDOC BEGIN="1">
<EDI_DC40 SEGMENT="1">
<SNDPOR></SNDPOR>
<SNDPRT></SNDPRT>
<SNDPRN></SNDPRN>
<SNDLAD></SNDLAD>
</EDI_DC40>
<YCSMOTOR_KONF01 SEGMENT="1">
<KLU>TBD</KLU>
<TYP>TBD</TYP>
<YCSMOTOR_KONF02 SEGMENT="1">
<YCSSTKLID>
<xsl:value-of select="concat(ESN,'#',substring-before(GRAPHIC_NAME, '.'))"/>
</YCSSTKLID>
</YCSMOTOR_KONF02>
<!-- Test Muenchian grouping -->
<xsl:for-each select="/ns:MT_FlatFile_Lists_Cu/Cu_Records/Record[generate-id(key('grouping, concat(./ESN, ./GRAPHIC_NAME)))]"/>
<YCSMOTOR_KONF02 SEGMENT="1">
<YCSSTKLID>
<xsl:value-of select="concat(./ESN,'#',substring-before(./GRAPHIC_NAME, '.'))"/>
</YCSSTKLID>
</YCSMOTOR_KONF02>
<!-- End Muenchian -->
</YCSMOTOR_KONF01>
</IDOC>
</YCSMKO01>
</xsl:template>
</xsl:stylesheet>
Thank you very much in advance.
Solution 1:[1]
If I am guessing correctly, you want to do something like:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns="urn:las:pp:ss1:tar"
exclude-result-prefixes="ns">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="rec-by-esn" match="Record" use="ESN"/>
<xsl:key name="rec-by-grf" match="Record" use="concat(ESN, '|', GRAPHIC_NAME)"/>
<xsl:template match="/ns:MT_FlatFile_Lists_Cu">
<root>
<!-- group by ESN -->
<xsl:for-each select="Cu_Records/Record[generate-id() = generate-id(key('rec-by-esn', ESN))]">
<YCSMKO01>
<IDOC BEGIN="1">
<EDI_DC40 SEGMENT="1">
<SNDPOR></SNDPOR>
<SNDPRT></SNDPRT>
<SNDPRN></SNDPRN>
<SNDLAD></SNDLAD>
</EDI_DC40>
<!-- subgroup by ESN and GRAPHIC_NAME -->
<xsl:for-each select="key('rec-by-esn', ESN)[generate-id() = generate-id(key('rec-by-grf', concat(ESN, '|', GRAPHIC_NAME)))]">
<YCSMOTOR_KONF02 SEGMENT="1">
<YCSSTKLID>
<xsl:value-of select="concat(ESN,'#',substring-before(GRAPHIC_NAME, '.'))"/>
</YCSSTKLID>
</YCSMOTOR_KONF02>
</xsl:for-each>
</IDOC>
</YCSMKO01>
</xsl:for-each>
</root>
</xsl:template>
</xsl:stylesheet>
Note the way subgrouping is applied to the current group only, selected by the expression key('rec-by-esn', ESN).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
