• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 629
  • Last Modified:

Counting nodes using XSLT

Im transforming XML document to HTML using XSLT stylesheet, here is example:
<?xml version="1.0" encoding="utf-8"?>
<catalog>
  <book>
    <title>3D Game Engine Programming</title>
    <publisher>Course</publisher>
    <year>2006</year>
    <hash>/FwgKyKg3ZZ+PCPiDFwcSQrP6AY=</hash>
    <file>Course.PTR.3D.Game.Engine.Programming.eBook-LinG.pdf</file>
  </book>
  <book>
    <title>A Programmer's Introduction to C#</title>
    <publisher>Apress</publisher>
    <year>2000</year>
    <hash>4nAXdx8xCA44tkUbAuGjzYVq5b4=</hash>
    <file>APress A Programmer's Introduction to C#.pdf</file>
  </book>
</catalog>

whole document is much longer, of course.
Now i need to create html table which will contain all publishers found in XML file and count of books they published, for example:
Publisher Published
Apress        10
Wiley          20

etc...

Sofar i have this code:

<xsl:for-each select="/catalog/book">
            <td>
                <xsl:value-of select="publisher"/>
            </td>
            <td>
                <xsl:value-of select="count(//publisher[.=current()/publisher])"/>
            </td>
</xsl:for-each>

this counts number of published books, but they are repeating for each book so output looks like this:
Apress 50
Wiley   20
Wiley   20
Apress 50
.....

Any ideas how to get right output? Thanks
0
zajda82
Asked:
zajda82
  • 3
1 Solution
 
Geert BormansCommented:
Hi zajda82,

you could limit your loop to just once per unique publisher

<xsl:for-each select="/catalog/book[not(publisher = preceding::book/publisher)]">
            <td>
                <xsl:value-of select="publisher"/>
            </td>
            <td>
                <xsl:value-of select="count(//publisher[.=current()/publisher])"/>
            </td>
</xsl:for-each>

in my next post I will show how to group using keys,
that has a better performance

Cheers!
0
 
Geert BormansCommented:
zajda82,

here is a solution using keys
This grouping method is known as the muenchian grouping algorithm

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:key name="book-by-publ" match="book" use="publisher"/>
    <xsl:template match="/">
        <html>
            <head></head>
            <body>
                <table>
                    <xsl:for-each select="//book[generate-id() = generate-id(key('book-by-publ', publisher)[1])]">
                        <xsl:variable name="pub" select="publisher"/>
                        <tr>
                            <td><xsl:value-of select="$pub"/></td>
                            <td><xsl:value-of select="count(//book[publisher = $pub])"/></td>
                        </tr>
                    </xsl:for-each>
                </table>
            </body>
        </html>
     </xsl:template>
</xsl:stylesheet>

check out this article for understanding
http://www.jenitennison.com/xslt/grouping/muenchian.xml
0
 
zajda82Author Commented:
awesome answer m8, thanks a lot!!!!
0
 
Geert BormansCommented:
welcome
0

Featured Post

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now