Reputation: 21
The HandlingUnitItem (/HandlingUnit/HandlingUnitItem/HandlingUnit/HandlingUnitItem) in the XML path getting repeated in the XML output. I'm not able to figure out why it was getting repeated in the Output.
I'm attaching the Input XML, XSLT code and the Output XML for your reference. exslt:node-set($Contents) what's this Content variable is holding?
Input xml :
<?xml version="1.0" encoding="UTF-8"?>
<SHPMNT05>
<IDOC BEGIN="1">
<E1EDT20 SEGMENT="1">
<TKNUM>0001960714</TKNUM>
<SHTYP>DEFC</SHTYP>
<ABFER>1</ABFER>
<ABWST>1</ABWST>
<BFART>2</BFART>
<E1EDL20 SEGMENT="1">
<VBELN>0076668882</VBELN>
<BTGEW>1.601</BTGEW>
<NTGEW>1.584</NTGEW>
<GEWEI>KGM</GEWEI>
<E1EDL37 SEGMENT="1">
<EXIDV>00000000000109126078</EXIDV>
<TARAG>0.001</TARAG>
<GWEIT>KGM</GWEIT>
<BRGEW>0.001</BRGEW>
<NTGEW>0.000</NTGEW>
<GWEIM>KGM</GWEIM>
<VHILM>PM-3215</VHILM>
<LAENG>0.000</LAENG>
<BREIT>0.000</BREIT>
<HOEHE>0.000</HOEHE>
<VHILM_KU>KC2</VHILM_KU>
<VEBEZ>VDA-KLT R 3215</VEBEZ>
<SMGKN>S</SMGKN>
<E1EDL38 SEGMENT="1">
<MAGRV_BEZ>Ben</MAGRV_BEZ>
<VEBEZ>VDA</VEBEZ>
</E1EDL38>
<E1EDL44 SEGMENT="1">
<VELIN>1</VELIN>
<VBELN>0076668882</VBELN>
<POSNR>000010</POSNR>
<VEMNG>1600.000</VEMNG>
<VEMEH>PCE</VEMEH>
<MATNR>8993601404</MATNR>
<WERKS>DCXX</WERKS>
<LGORT>S002</LGORT>
</E1EDL44>
</E1EDL37>
<E1EDL37 SEGMENT="1">
<EXIDV>00000000000109126079</EXIDV>
<TARAG>0.000</TARAG>
<GWEIT>KGM</GWEIT>
<BRGEW>1.614</BRGEW>
<NTGEW>1.614</NTGEW>
<GWEIM>KGM</GWEIM>
<VHILM>PM-9999</VHILM>
<LAENG>0.000</LAENG>
<BREIT>0.000</BREIT>
<HOEHE>0.000</HOEHE>
<EXIDV2>040578630025545457</EXIDV2>
<VEBEZ>**********************</VEBEZ>
<SMGKN>M</SMGKN>
<E1EDL38 SEGMENT="1">
<VHART_BEZ>Palette</VHART_BEZ>
<MAGRV_BEZ>Ben</MAGRV_BEZ>
<VEBEZ>**********************</VEBEZ>
</E1EDL38>
<E1EDL44 SEGMENT="1">
<VELIN>3</VELIN>
<EXIDV>00000000000109126078</EXIDV>
</E1EDL44>
</E1EDL37>
</E1EDL20>
</E1EDT20>
</IDOC>
</SHPMNT05>
XSLT Code :
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" extension-element-prefixes="exslt">
<xsl:template match="/">
<xsl:choose>
<xsl:when test="/*/IDOC/E1EDT20">
<xsl:for-each select="/*/IDOC/E1EDT20|/*/IDOC[E1EDL20]">
<xsl:for-each select="E1EDL20/E1EDL37[not(EXIDV=/*/IDOC/E1EDT20/E1EDL20/E1EDL37/E1EDL44/EXIDV)]">
<xsl:sort select="EXIDV"/>
<xsl:value-of select="EXIDV"/>
<xsl:call-template name="HUTree"/>
</xsl:for-each>
</xsl:for-each>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="HUTree">
<HandlingUnit>
<xsl:attribute name="key">
<xsl:value-of select="concat(VHILM,VHILM_KU,SMGKN,LAENG,BREIT,HOEHE,BRGEW,NTGEW,GWEIM)"/>
<xsl:for-each select="E1EDL44|E1EDT43">
<xsl:sort select="VELIN" order="descending"/>
<xsl:sort select="MATNR"/>
<xsl:value-of select="concat(VELIN,EXIDV,MATNR,VBELN,POSNR,VEMNG,VEMEH,KDMAT)"/>
</xsl:for-each>
</xsl:attribute>
<xsl:copy-of select="EXIDV|VHILM|VHILM_KU|SMGKN|LAENG|BREIT|HOEHE|BRGEW|NTGEW|GWEIM"/>
<xsl:variable name="Contents">
<xsl:for-each select="E1EDL44|E1EDT43">
<xsl:sort select="VELIN" order="descending"/>
<xsl:sort select="MATNR"/>
<xsl:variable name="VBELN" select="VBELN"/>
<xsl:variable name="POSNR" select="POSNR"/>
<HandlingUnitItem>
<xsl:copy-of select="VELIN|MATNR|VBELN|POSNR|VEMNG|VEMEH|KDMAT"/>
<xsl:copy-of select="/*/IDOC/E1EDT20/E1EDL20[VBELN=$VBELN]/E1EDL24[POSNR=$POSNR]/E1EDL41[QUALI='001']/BSTNR"/>
<xsl:for-each select="../../E1EDL20/E1EDL37[EXIDV=current()/EXIDV] | ../../../E1EDL20/E1EDL37[EXIDV=current()/EXIDV]">
<xsl:sort select="EXIDV"/>
<xsl:call-template name="HUTree"/>
</xsl:for-each>
</HandlingUnitItem>
</xsl:for-each>
</xsl:variable>
<xsl:copy-of select="$Contents"/>
<xsl:for-each select="exslt:node-set($Contents)/HandlingUnitItem[not(HandlingUnit/@key=preceding-sibling::HandlingUnitItem/HandlingUnit/@key)]">
<HandlingUnitItem>
<xsl:copy-of select="VELIN|MATNR|VBELN|POSNR|VEMNG|VEMEH|KDMAT|BSTNR"/>
<xsl:if test="HandlingUnit">
<HandlingUnit>
<xsl:variable name="str">
<xsl:for-each select=".|following-sibling::HandlingUnitItem[HandlingUnit/@key=current()/HandlingUnit/@key]">
<xsl:if test="position()!=1 and HandlingUnit/EXIDV!=preceding-sibling::HandlingUnitItem[HandlingUnit/@key=current()/HandlingUnit/@key][1]/HandlingUnit/EXIDV+1">
<xsl:value-of select="'|'"/>
</xsl:if>
<xsl:value-of select="concat(HandlingUnit/EXIDV,',')"/>
</xsl:for-each>
</xsl:variable>
<OutputStr>
<xsl:value-of select="$str"/>
</OutputStr>
</HandlingUnit>
</xsl:if>
</HandlingUnitItem>
</xsl:for-each>
</HandlingUnit>
</xsl:template>
</xsl:stylesheet>
Output xml :
<?xml version='1.0' encoding='UTF-8' ?>
00000000000109126079<HandlingUnit key="PM-9999M0.0000.0000.0001.6141.614KGM300000000000109126078">
<EXIDV>00000000000109126079</EXIDV>
<BRGEW>1.614</BRGEW>
<NTGEW>1.614</NTGEW>
<GWEIM>KGM</GWEIM>
<VHILM>PM-9999</VHILM>
<LAENG>0.000</LAENG>
<BREIT>0.000</BREIT>
<HOEHE>0.000</HOEHE>
<SMGKN>M</SMGKN>
<HandlingUnitItem>
<VELIN>3</VELIN>
<HandlingUnit key="PM-3215KC2S0.0000.0000.0000.0010.000KGM1899360140400766688820000101600.000PCE">
<EXIDV>00000000000109126078</EXIDV>
<BRGEW>0.001</BRGEW>
<NTGEW>0.000</NTGEW>
<GWEIM>KGM</GWEIM>
<VHILM>PM-3215</VHILM>
<LAENG>0.000</LAENG>
<BREIT>0.000</BREIT>
<HOEHE>0.000</HOEHE>
<VHILM_KU>KC2</VHILM_KU>
<SMGKN>S</SMGKN>
<HandlingUnitItem>
<VELIN>1</VELIN>
<VBELN>0076668882</VBELN>
<POSNR>000010</POSNR>
<VEMNG>1600.000</VEMNG>
<VEMEH>PCE</VEMEH>
<MATNR>8993601404</MATNR>
<BSTNR>0057328890010</BSTNR>
</HandlingUnitItem>
<HandlingUnitItem>
<VELIN>1</VELIN>
<VBELN>0076668882</VBELN>
<POSNR>000010</POSNR>
<VEMNG>1600.000</VEMNG>
<VEMEH>PCE</VEMEH>
<MATNR>8993601404</MATNR>
<BSTNR>0057328890010</BSTNR>
</HandlingUnitItem>
</HandlingUnit>
</HandlingUnitItem>
<HandlingUnitItem>
<VELIN>3</VELIN>
<HandlingUnit>
<OutputStr>00000000000109126078,</OutputStr>
</HandlingUnit>
</HandlingUnitItem>
</HandlingUnit>
Upvotes: 2
Views: 64
Reputation: 16666
Please confirm whether this simplified example captures what you want to achieve:
<xsl:template match="a">
, the output is collected into $flat
.)key('key', ...)
returns the first node with a given key, generate-id
is used to check whether this is the current node.)<a key="1">
<a key="2">
<a key="1" />
</a>
</a>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exslt="http://exslt.org/common">
<xsl:key name="key" match="a" use="@key" />
<xsl:template match="/">
<xsl:variable name="flat">
<xsl:apply-templates select="a" />
</xsl:variable>
<flat>
<xsl:for-each
select="exslt:node-set($flat)/a[generate-id()=generate-id(key('key',@key))]">
<a key="{@key}" />
</xsl:for-each>
</flat>
</xsl:template>
<xsl:template match="a">
<a key="{@key}" /> <!-- Your key attribute is more complex -->
<xsl:apply-templates select="a" />
</xsl:template>
</xsl:stylesheet>
The condition with key
and generate-id
is not only faster than preceding-sibling::*
, it works even without storing the flattened list in a variable:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="key" match="a" use="@key" />
<xsl:template match="/">
<flat>
<xsl:apply-templates select="a" />
</flat>
</xsl:template>
<xsl:template match="a">
<xsl:if test="generate-id()=generate-id(key('key',@key))">
<a key="{@key}" />
</xsl:if>
<xsl:apply-templates select="a" />
</xsl:template>
</xsl:stylesheet>
(This last trick may not be applicable to your case, because your key
attribute is computed from many key properties. Or is it? Many properties that make up your key
are in fact measures like weight or height, I cannot imagine that these are really key components.)
Upvotes: 0