2

How do i group the elements below using 'insref' and 'pref' I have tried using generate key id in xslt version 1.

XML :

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<catalog>
   <mylist>
    <cd id="1" insref="#10">
        <title>Empire Burlesque</title>
        <artist>Bob Dylan</artist>
        <country>USA</country>
        <company>Columbia</company>
        <price>10.90</price>
        <year>1985</year>
    </cd>
    <cd id ="2" insref="#20" pref="#1">
        <title>Hide your heart</title>
        <artist>Bonnie Tyler</artist>
        <country>UK</country>
        <company>CBS Records</company>
        <price>9.90</price>
        <year>1988</year>
    </cd>
    <cd id="3" insref="#520" pref="#1">
        <title>Lonly heart</title>
        <artist>Bonnie Tyler</artist>
        <country>UK</country>
        <company>CBS Records</company>
        <price>9.90</price>
        <year>1988</year>
    </cd>
    <cd id="4" insref="#56" pref="#1">
        <title>Still got the blues</title>
        <artist>Gary Moore</artist>
        <country>UK</country>
        <company>Virgin records</company>
        <price>10.20</price>
        <year>1990</year>
    </cd>
    <cd id="5" insref="#56" pref="#2">
        <title>Still got the blues</title>
        <artist>Gary Moore</artist>
        <country>UK</country>
        <company>Virgin records</company>
        <price>10.20</price>
        <year>1990</year>
    </cd>
    <cd id="6" insref="#56" pref="#2">
        <title>Still got the blues</title>
        <artist>Gary Moore</artist>
        <country>UK</country>
        <company>Virgin records</company>
        <price>10.20</price>
        <year>1990</year>
    </cd>
    <cd id="7" insref="#56" pref="#2">
        <title>Still got the blues</title>
        <artist>Gary Moore</artist>
        <country>UK</country>
        <company>Virgin records</company>
        <price>10.20</price>
        <year>1990</year>
    </cd>
    <cd id="8" insref="#78" pref="#2">
        <title>Maggie May</title>
        <artist>Rod Stewart</artist>
        <country>UK</country>
        <company>Pickwick</company>
        <price>8.50</price>
        <year>1990</year>
    </cd>
    <cd id="9" insref="#45" pref="#1">
        <title>Romanza</title>
        <artist>Andrea Bocelli</artist>
        <country>EU</country>
        <company>Polydor</company>
        <price>10.80</price>
        <year>1996</year>
    </cd>

    <cd id="10" insref="#45" pref="#2">
        <title>Romanza</title>
        <artist>Andrea Bocelli</artist>
        <country>EU</country>
        <company>Polydor</company>
        <price>10.80</price>
        <year>1996</year>
    </cd>
 </mylist>  
</catalog>

Desired result:

TITLE               ARTIST          ID  INSREF  PREF    Qty
Empire Burlesque    Bob Dylan       1   10      
Hide your heart     Bonnie Tyler    2   20      1       1   
Lonly heart         Bonnie Tyler    3   520     1       1       
Still got the blues Gary Moore      4   56      1       1   
Still got the blues Gary Moore      4   56      2       3   
Maggie May          Rod Stewart     8   78      2       1   
Romanza             Andrea Bocelli  9   45      1       1
Romanza             Andrea Bocelli  10  45      2       1

Here is what i have. I'm using the key generate function also. Any idea what is wrong with this xslt. As for the count i was thinking of getting the unique key count.

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:key name="by-accessRefs" match="cd" use="concat(@insref,@pref)"/>

<xsl:template match="/">
  <html>
  <body>
    <h2>My CD Collection</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>Title</th>
        <th>Artist</th>
        <th>INSREF</th>
         <th>PREF</th>
      </tr>
      <xsl:for-each select="catalog/mylist/cd[generate-id(.) = generate-id(key('by-accessRefs',concat(@insref,@pref)[1])]">

         <tr>
        <td><xsl:value-of select="title"/></td>
        <td><xsl:value-of select="artist"/></td>
        <td><xsl:value-of select="@insref"/></td>
        <td><xsl:value-of select="@pref"/></td>
      </tr>
      </xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>

</xsl:stylesheet>

2 Answers2

1

This XSLT 1.0 transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kCDByProps" match="cd" use=
  "concat(title,'+',artist,'+',@insref,'+',@pref)"/>

 <xsl:template match="/*">
     <table>
       <thead>
         <tr>
           <td>TITLE</td><td>ARTIST</td><td>ID</td><td>INSREF</td><td>PREF</td><td>Qty</td>
         </tr>
       </thead>
       <xsl:apply-templates select=
        "mylist/cd
            [generate-id()
            =
             generate-id(key('kCDByProps', 
                               concat(title,'+',artist,'+',@insref,'+',@pref)
                              )[1])
            ]
        "/>
     </table>
 </xsl:template>

 <xsl:template match="cd">
  <xsl:variable name="vGroup" select=
    "key('kCDByProps', concat(title,'+',artist,'+',@insref,'+',@pref))"/>

  <tr>
    <td><xsl:value-of select="title"/></td>
    <td><xsl:value-of select="artist"/></td>
    <td><xsl:value-of select="@id"/></td>
    <td><xsl:value-of select="substring(@insref, 2)"/></td>
    <td><xsl:value-of select="substring(@pref, 2)"/></td>
    <xsl:variable name="vCount" select=
           "count($vGroup[@pref = current()/@pref])"/>
    <td>
        <xsl:if test="$vCount"><xsl:value-of select="$vCount"/></xsl:if>
    </td>
  </tr>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<catalog>
    <mylist>
        <cd id="1" insref="#10">
            <title>Empire Burlesque</title>
            <artist>Bob Dylan</artist>
            <country>USA</country>
            <company>Columbia</company>
            <price>10.90</price>
            <year>1985</year>
        </cd>
        <cd id ="2" insref="#20" pref="#1">
            <title>Hide your heart</title>
            <artist>Bonnie Tyler</artist>
            <country>UK</country>
            <company>CBS Records</company>
            <price>9.90</price>
            <year>1988</year>
        </cd>
        <cd id="3" insref="#520" pref="#1">
            <title>Lonly heart</title>
            <artist>Bonnie Tyler</artist>
            <country>UK</country>
            <company>CBS Records</company>
            <price>9.90</price>
            <year>1988</year>
        </cd>
        <cd id="4" insref="#56" pref="#1">
            <title>Still got the blues</title>
            <artist>Gary Moore</artist>
            <country>UK</country>
            <company>Virgin records</company>
            <price>10.20</price>
            <year>1990</year>
        </cd>
        <cd id="5" insref="#56" pref="#2">
            <title>Still got the blues</title>
            <artist>Gary Moore</artist>
            <country>UK</country>
            <company>Virgin records</company>
            <price>10.20</price>
            <year>1990</year>
        </cd>
        <cd id="6" insref="#56" pref="#2">
            <title>Still got the blues</title>
            <artist>Gary Moore</artist>
            <country>UK</country>
            <company>Virgin records</company>
            <price>10.20</price>
            <year>1990</year>
        </cd>
        <cd id="7" insref="#56" pref="#2">
            <title>Still got the blues</title>
            <artist>Gary Moore</artist>
            <country>UK</country>
            <company>Virgin records</company>
            <price>10.20</price>
            <year>1990</year>
        </cd>
        <cd id="8" insref="#78" pref="#2">
            <title>Maggie May</title>
            <artist>Rod Stewart</artist>
            <country>UK</country>
            <company>Pickwick</company>
            <price>8.50</price>
            <year>1990</year>
        </cd>
        <cd id="9" insref="#45" pref="#1">
            <title>Romanza</title>
            <artist>Andrea Bocelli</artist>
            <country>EU</country>
            <company>Polydor</company>
            <price>10.80</price>
            <year>1996</year>
        </cd>
        <cd id="10" insref="#45" pref="#2">
            <title>Romanza</title>
            <artist>Andrea Bocelli</artist>
            <country>EU</country>
            <company>Polydor</company>
            <price>10.80</price>
            <year>1996</year>
        </cd>
    </mylist>
</catalog>

produces the following HTML output:

<table>
   <thead>
      <tr>
         <td>TITLE</td>
         <td>ARTIST</td>
         <td>ID</td>
         <td>INSREF</td>
         <td>PREF</td>
         <td>Qty</td>
      </tr>
   </thead>
   <tr>
      <td>Empire Burlesque</td>
      <td>Bob Dylan</td>
      <td>1</td>
      <td>10</td>
      <td/>
      <td/>
   </tr>
   <tr>
      <td>Hide your heart</td>
      <td>Bonnie Tyler</td>
      <td>2</td>
      <td>20</td>
      <td>1</td>
      <td>1</td>
   </tr>
   <tr>
      <td>Lonly heart</td>
      <td>Bonnie Tyler</td>
      <td>3</td>
      <td>520</td>
      <td>1</td>
      <td>1</td>
   </tr>
   <tr>
      <td>Still got the blues</td>
      <td>Gary Moore</td>
      <td>4</td>
      <td>56</td>
      <td>1</td>
      <td>1</td>
   </tr>
   <tr>
      <td>Still got the blues</td>
      <td>Gary Moore</td>
      <td>5</td>
      <td>56</td>
      <td>2</td>
      <td>3</td>
   </tr>
   <tr>
      <td>Maggie May</td>
      <td>Rod Stewart</td>
      <td>8</td>
      <td>78</td>
      <td>2</td>
      <td>1</td>
   </tr>
   <tr>
      <td>Romanza</td>
      <td>Andrea Bocelli</td>
      <td>9</td>
      <td>45</td>
      <td>1</td>
      <td>1</td>
   </tr>
   <tr>
      <td>Romanza</td>
      <td>Andrea Bocelli</td>
      <td>10</td>
      <td>45</td>
      <td>2</td>
      <td>1</td>
   </tr>
</table>

which when viewed in a browser seems to be the wanted correct result:

enter image description here

Dimitre Novatchev
  • 240,661
  • 26
  • 293
  • 431
  • Thanks Dimitre ! that worked. I was trying something similar but it did not work for me ...I have posted that as an update can you see where i went wrong. Thanks again ! – renni eappen Apr 29 '12 at 15:31
  • @rennieappen: You are welcome. I had a look at your code and there are syntax errors that the XSLT processor should report to you. Then you need to correct these. – Dimitre Novatchev Apr 29 '12 at 15:50
  • Thank you sir. I'm using the w3 school on line editor. Does not help much with syntax errors. As you mentioned i should get a proper editor. – renni eappen Apr 29 '12 at 16:01
  • 1
    @rennieappen: Saxon 6.5.x is a good XSLT 1.0 XSLT processor. If you are new to XSLT I would recommend to start using XSLT 2.0 --Saxon 9 is a good choice. Kernow is a graphical inteface to Saxon. If you are limited to using XSLT 1.0 and do have Visual Studio, you can use its XML Editor combined with the XSLT Debugger. Another choce (both with XSLT 1.0 or 2.0) is oXygen. – Dimitre Novatchev Apr 29 '12 at 16:07
  • Thanks for sharing this information. Appreciate all the help. – renni eappen Apr 29 '12 at 19:48
0

I assumed that the output you need is an HTML table:

The Stylesheet file

<?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"
    xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
    exclude-result-prefixes="xs xd"
    version="2.0">

    <xsl:output method="html" indent="yes"/>

    <xsl:key name="kTitle" match="title" use="text()"/>

    <xsl:template match="/">
        <table>
            <thead>
                <tr>
                    <th>TITLE</th>
                    <th>ARTIST</th>
                    <th>ID</th>
                    <th>INSREF</th>
                    <th>PREF</th>
                    <th>Qty</th>
                </tr>
            </thead>
            <tbody>
                <xsl:for-each-group select="//cd" group-by="@id">
                    <tr>
                        <td><xsl:value-of select="title"/></td>
                        <td><xsl:value-of select="artist"/></td>
                        <td><xsl:value-of select="@id"/></td>
                        <td><xsl:value-of select="substring-after(@insref,'#')"/></td>
                        <td><xsl:value-of select="substring-after(@pref,'#')"/></td>
                        <td><xsl:value-of select="count(key('kTitle',title/text()))"/></td>
                    </tr>
                </xsl:for-each-group>
            </tbody>
        </table>
    </xsl:template>

</xsl:stylesheet>

The result-document:

<table>
   <thead>
      <tr>
         <th>TITLE</th>
         <th>ARTIST</th>
         <th>ID</th>
         <th>INSREF</th>
         <th>PREF</th>
         <th>Qty</th>
      </tr>
   </thead>
   <tbody>
      <tr>
         <td>Empire Burlesque</td>
         <td>Bob Dylan</td>
         <td>1</td>
         <td>10</td>
         <td></td>
         <td>1</td>
      </tr>
      <tr>
         <td>Hide your heart</td>
         <td>Bonnie Tyler</td>
         <td>2</td>
         <td>20</td>
         <td>1</td>
         <td>1</td>
      </tr>
      <tr>
         <td>Lonly heart</td>
         <td>Bonnie Tyler</td>
         <td>3</td>
         <td>520</td>
         <td>1</td>
         <td>1</td>
      </tr>
      <tr>
         <td>Still got the blues</td>
         <td>Gary Moore</td>
         <td>4</td>
         <td>56</td>
         <td>1</td>
         <td>4</td>
      </tr>
      <tr>
         <td>Still got the blues</td>
         <td>Gary Moore</td>
         <td>5</td>
         <td>56</td>
         <td>2</td>
         <td>4</td>
      </tr>
      <tr>
         <td>Still got the blues</td>
         <td>Gary Moore</td>
         <td>6</td>
         <td>56</td>
         <td>2</td>
         <td>4</td>
      </tr>
      <tr>
         <td>Still got the blues</td>
         <td>Gary Moore</td>
         <td>7</td>
         <td>56</td>
         <td>2</td>
         <td>4</td>
      </tr>
      <tr>
         <td>Maggie May</td>
         <td>Rod Stewart</td>
         <td>8</td>
         <td>78</td>
         <td>2</td>
         <td>1</td>
      </tr>
      <tr>
         <td>Romanza</td>
         <td>Andrea Bocelli</td>
         <td>9</td>
         <td>45</td>
         <td>1</td>
         <td>2</td>
      </tr>
      <tr>
         <td>Romanza</td>
         <td>Andrea Bocelli</td>
         <td>10</td>
         <td>45</td>
         <td>2</td>
         <td>2</td>
      </tr>
   </tbody>
</table>
Cylian
  • 10,970
  • 4
  • 42
  • 55