Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Marko Ivanovski 14 posts 124 karma points
    Oct 14, 2010 @ 22:57
    Marko Ivanovski
    0

    Grouping XML nodes by Month and Year in XSLT

    Hi everyone,

    I've started a topic on Stack Overflow related to grouping XML nodes by Month And Year for a custom Blog that I've built.

    To keep this post clean and readable, I've provided a link to the question so you can see my XML but I'll post the answer I've received here. Please see if you can tell what's wrong with it.

    <xsl:stylesheet version="1.0"
     
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     
    xmlns:m="my:months" exclude-result-prefixes="m" >
     
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

     
    <m:months>
       
    <m>January</m>
       
    <m>February</m>
       
    <m>March</m>
       
    <m>April</m>
       
    <m>May</m>
       
    <m>June</m>
       
    <m>July</m>
       
    <m>August</m>
       
    <m>September</m>
       
    <m>October</m>
       
    <m>November</m>
       
    <m>December</m>
     
    </m:months>

     
    <xsl:variable name="vMonthNames" select=
     
    "document('')/*/m:months/*"/>

     
    <xsl:key name="kPostsByYear" match="BlogPost"
     
    use="substring-before(
                  (@createDate|archiveUnder)[last()],
                  '-'
                            )"
    />

     
    <xsl:key name="kPostsByYearMonth" match="BlogPost"
     
    use="substring((@createDate|archiveUnder)[last()],
                     1,7
                     )"
    />

     
    <xsl:template match="/*">
       
    <ul>
       
    <xsl:apply-templates mode="year" select=
         
    "*/*/BlogPost
              [generate-id()
              =
               generate-id(key('kPostsByYear',
                           substring-before(
                             (@createDate|archiveUnder)[last()],
                              '-'
                                            )
                                )[1]
                           )
                  ]
         "
    >
           
    <xsl:sort order="descending" select=
           
    "substring-before(
                (@createDate|archiveUnder)[last()],
                 '-'
                              )
            "
    />
       
    </xsl:apply-templates>
     
    </ul>
     
    </xsl:template>

     
    <xsl:template match="BlogPost" mode="year">
     
    <xsl:variable name="vYear" select=
       
    "substring-before((@createDate|archiveUnder)[last()],
                          '-')
        "
    />
     
    <xsl:variable name="vyearBlogs"
                   
    select="key('kPostsByYear',$vYear)"/>
     
    <li>
       
    <h3><xsl:value-of select="$vYear"/></h3>
       
    <ul>
         
    <xsl:apply-templates mode="month" select=
             
    "$vyearBlogs
                 [generate-id()
                 =
                  generate-id(key('kPostsByYearMonth',
                              substring((@createDate|archiveUnder)[last()],
                                         1,7
                                        )
                                  )[1]
                              )
                  ]
              "
    >
             
    <xsl:sort order="descending" select=
               
    "substring((@createDate|archiveUnder)[last()],6,2)"
             
    />
         
    </xsl:apply-templates>
       
    </ul>
     
    </li>
     
    </xsl:template>

     
    <xsl:template match="BlogPost" mode="month">
     
    <xsl:variable name="vMonth" select=
       
    "substring((@createDate|archiveUnder)[last()],6,2)"/>

     
    <xsl:variable name="vmonthsBlogs" select=
       
    "key('kPostsByYearMonth',
             substring((@createDate|archiveUnder)[last()],1,7)
             )"
    />
     
    <li><xsl:value-of select=
           
    "concat($vMonthNames[position()=$vMonth],
                    ' (',
                    count($vmonthsBlogs),
                    ')'
                    )"
    />
     
    </li>
     
    </xsl:template>
    </xsl:stylesheet>

    Note, Because Umbraco uses $currentPage, I tried replacing the

    */*/BlogPost

    with

    $currentPage/descendant::BlogPost

    but that throws a weird error

    For security reasons DTD is prohibited in this XML document. To enable 
    DTD processing set the DtdProcessing property on XmlReaderSettings to 
    Parse and pass the settings into XmlReader.Create method.
    

    I found another post here with the same error which suggested adding urn: before the xmlns:m="my:months" but that didn't help either.

    The entire code is a bit out of my league, so any help is appreciated.

Please Sign in or register to post replies

Write your reply to:

Draft