Reputation: 107
I've got an XML like that :
<produits>
<produit>
<CAT>GENCABI</CAT>
<ITEMCODE>100-0190</ITEMCODE>
<DESCR>Broches Henry Schein Longueur 21Mm Taille 40</DESCR>
<EXTDESC>Broches Henry Schein Longueur 21Mm Taille 40</EXTDESC>
<ITEMSET>100-9231</ITEMSET>
<MANUF>1</MANUF>
<IMAGE>100-0190</IMAGE>
<TOC>8</TOC>
<SUBTOC>3</SUBTOC>
</produit>
<produit>
<CAT>GENCABI</CAT>
<ITEMCODE>100-0240</ITEMCODE>
<DESCR>Racleurs 25Mm No40 (6) Schein</DESCR>
<EXTDESC>Racleurs 25Mm No40 (6) Schein</EXTDESC>
<ITEMSET>100-9231</ITEMSET>
<MANUF>1</MANUF>
<IMAGE>100-0240</IMAGE>
<TOC>8</TOC>
<SUBTOC>3</SUBTOC>
</produit>
<produit>
<CAT>GENCABI</CAT>
<ITEMCODE>100-0379</ITEMCODE>
<DESCR>Finger Plugger Henry Schein 25Mm B</DESCR>
<EXTDESC>Pour condensation laterale de la gutta manche plastique. Rouge</EXTDESC>
<ITEMSET>100-8766</ITEMSET>
<MANUF>1</MANUF>
<IMAGE>100-8766</IMAGE>
<TOC>8</TOC>
<SUBTOC>9</SUBTOC>
</produit>
</produits>
I try to group Item by "Itemset". I do it with a xsl like that :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output indent="yes"/>
<xsl:key name="produit-by-ITEMSET" match="produit" use="ITEMSET" />
<xsl:template match="/produits">
<xsl:copy>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="produit">
<xsl:if test="generate-id() = generate-id(key('produit-by-ITEMSET', ITEMSET)[1])">
<produit>
<xsl:attribute name="ParentItem">
<xsl:value-of select="ITEMSET"/>
</xsl:attribute>
<xsl:for-each select="../produit[ITEMSET=current()/ITEMSET]">
<child>
<xsl:copy-of select="ITEMCODE" />
<xsl:copy-of select="DESCR" />
<xsl:copy-of select="EXTDESC" />
<xsl:copy-of select="MANUF" />
<xsl:copy-of select="IMAGE" />
</child>
</xsl:for-each>
</produit>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
I got What I whant for Item with multiples "Child" but I want to get rid of "Child" tag if there is only one child.
In my mind I've got something like "if count(select childs) > 1 display child tag, else didn't put child tag". But i'm pretty new with xsl / xml and a lillte bit lost... If anyone have a tips...
Edit : Add xml output I have & I want
Output I have :
<produits>
<produit ParentItem="100-9231">
<child>
<ITEMCODE>100-0190</ITEMCODE>
<DESCR>Broches Henry Schein Longueur 21Mm Taille 40</DESCR>
<EXTDESC>Broches Henry Schein Longueur 21Mm Taille 40</EXTDESC>
<MANUF>1</MANUF>
<IMAGE>100-0190</IMAGE>
</child>
<child>
<ITEMCODE>100-0583</ITEMCODE>
<DESCR>Broches Henry Schein Longueur 21Mm Taille 30</DESCR>
<EXTDESC>Broches Henry Schein Longueur 21Mm Taille 30</EXTDESC>
<MANUF>1</MANUF>
<IMAGE>100-0583</IMAGE>
</child>
<child>
<ITEMCODE>100-0720</ITEMCODE>
<DESCR>Broches Henry Schein Longueur 21 Mm Taille 15</DESCR>
<EXTDESC>Broches Henry Schein Longueur 21 Mm Taille 15</EXTDESC>
<MANUF>1</MANUF>
<IMAGE>100-0720</IMAGE>
</child>
</produit>
<produit ParentItem="968-2000">
<child>
<ITEMCODE>968-2000</ITEMCODE>
<DESCR>Aiguilles Medicales Terumo</DESCR>
<EXTDESC></EXTDESC>
<MANUF>5048</MANUF>
<IMAGE>968-2000</IMAGE>
</child>
</produit>
</produits>
Output I want :
<produits>
<produit ParentItem="100-9231">
<child>
<ITEMCODE>100-0190</ITEMCODE>
<DESCR>Broches Henry Schein Longueur 21Mm Taille 40</DESCR>
<EXTDESC>Broches Henry Schein Longueur 21Mm Taille 40</EXTDESC>
<MANUF>1</MANUF>
<IMAGE>100-0190</IMAGE>
</child>
<child>
<ITEMCODE>100-0583</ITEMCODE>
<DESCR>Broches Henry Schein Longueur 21Mm Taille 30</DESCR>
<EXTDESC>Broches Henry Schein Longueur 21Mm Taille 30</EXTDESC>
<MANUF>1</MANUF>
<IMAGE>100-0583</IMAGE>
</child>
<child>
<ITEMCODE>100-0720</ITEMCODE>
<DESCR>Broches Henry Schein Longueur 21 Mm Taille 15</DESCR>
<EXTDESC>Broches Henry Schein Longueur 21 Mm Taille 15</EXTDESC>
<MANUF>1</MANUF>
<IMAGE>100-0720</IMAGE>
</child>
</produit>
<produit ParentItem="968-2000">
<ITEMCODE>968-2000</ITEMCODE>
<DESCR>Aiguilles Medicales Terumo</DESCR>
<EXTDESC></EXTDESC>
<MANUF>5048</MANUF>
<IMAGE>968-2000</IMAGE>
</produit>
</produits>
Upvotes: 0
Views: 192
Reputation: 70648
I am guessing you that you want your output to look like this....
<produits>
<produit ParentItem="100-9231">
<child>
<ITEMCODE>100-0190</ITEMCODE>
<DESCR>Broches Henry Schein Longueur 21Mm Taille 40</DESCR>
<EXTDESC>Broches Henry Schein Longueur 21Mm Taille 40</EXTDESC>
<MANUF>1</MANUF>
<IMAGE>100-0190</IMAGE>
</child>
<child>
<ITEMCODE>100-0240</ITEMCODE>
<DESCR>Racleurs 25Mm No40 (6) Schein</DESCR>
<EXTDESC>Racleurs 25Mm No40 (6) Schein</EXTDESC>
<MANUF>1</MANUF>
<IMAGE>100-0240</IMAGE>
</child>
</produit>
<produit ParentItem="100-8766">
<ITEMCODE>100-0379</ITEMCODE>
<DESCR>Finger Plugger Henry Schein 25Mm B</DESCR>
<EXTDESC>Pour condensation laterale de la gutta manche plastique. Rouge</EXTDESC>
<MANUF>1</MANUF>
<IMAGE>100-8766</IMAGE>
</produit>
</produits>
First thing to mention is that your xsl:for-each can actually use the key to get the 'child' items in the 'group'
<xsl:for-each select="key('produit-by-ITEMSET', ITEMSET)">
To avoid duplication of code, I would create a template to output the child items (without the child element though)
<xsl:template match="produit" mode="child">
<xsl:copy-of select="ITEMCODE" />
<xsl:copy-of select="DESCR" />
<xsl:copy-of select="EXTDESC" />
<xsl:copy-of select="MANUF" />
<xsl:copy-of select="IMAGE" />
</xsl:template>
Then, you can test how many child items there are by counting the key
<xsl:choose>
<xsl:when test="count(key('produit-by-ITEMSET', ITEMSET)) > 1">
<!-- Multiple children -->
</xsl:when>
<xsl:otherwise>
<-- One child -->
</xsl:otherwise>
</xsl:choose>
For multiple children, use the current for-each loop, but call the template
<xsl:for-each select="key('produit-by-ITEMSET', ITEMSET)">
<child>
<xsl:apply-templates select="." mode="child" />
</child>
</xsl:for-each>
For single children, simply call the template without creating the child.
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output indent="yes"/>
<xsl:key name="produit-by-ITEMSET" match="produit" use="ITEMSET" />
<xsl:template match="/produits">
<xsl:copy>
<xsl:apply-templates select="*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="produit">
<xsl:if test="generate-id() = generate-id(key('produit-by-ITEMSET', ITEMSET)[1])">
<produit>
<xsl:attribute name="ParentItem">
<xsl:value-of select="ITEMSET"/>
</xsl:attribute>
<xsl:choose>
<xsl:when test="count(key('produit-by-ITEMSET', ITEMSET)) > 1">
<xsl:for-each select="key('produit-by-ITEMSET', ITEMSET)">
<child>
<xsl:apply-templates select="." mode="child" />
</child>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="child" />
</xsl:otherwise>
</xsl:choose>
</produit>
</xsl:if>
</xsl:template>
<xsl:template match="produit" mode="child">
<xsl:copy-of select="ITEMCODE" />
<xsl:copy-of select="DESCR" />
<xsl:copy-of select="EXTDESC" />
<xsl:copy-of select="MANUF" />
<xsl:copy-of select="IMAGE" />
</xsl:template>
</xsl:stylesheet>
Upvotes: 1