Search code examples
xmlxsltumbracoumbraco7

Get count using XSLT


I have a Doc Type called Blog - In short everything under a content node can create a blog. Along with this is the date for the blog. I'm trying to count the number of blogs for each month using XSLT and have the below but is giving me the incorrect count?

<xsl:key name="MonthNo" match="Blog" use="substring(concat(currentDate, @createDate), 1,7)"/>

<xsl:template match="Blog" mode="month">
<xsl:variable name="DateBlog" select="concat(currentDate, @createDate)"/>
<xsl:variable name="YearBlog" select="substring-before($DateBlog, '-')"/>
<xsl:variable name="MonthBlog" select="substring($DateBlog,6,2)"/>
<xsl:variable name="BlogsInMonth" select="key('MonthNo', substring($DateBlog,1,7))"/>
<li>        
  <xsl:element name="a">
    <xsl:attribute name="href">
      <xsl:value-of select="umbraco.library:NiceUrl(1234)"/>?d=<xsl:value-of select="concat($MonthBlog, '-', $YearBlog)"/>
    </xsl:attribute>
    <xsl:value-of select="concat($monthNames[position()=$MonthBlog], ' (', count($BlogsInMonth),')')"/>
  </xsl:element>
</li>

Can anyone see where ive gone wrong or the mistake made? Struggling with this so any help is appreciated.


Solution

  • The way you use key function to get the number of blogs in particular month is corect. I created an example script, correcting a little your version (http://xsltransform.net/pNvs5vT), take a look at it.

    The source XML contains 6 Blog nodes, one created in September, two in October and three in November and the number is properly presented in the output.

    But I have some doubts about your original script and maybe the reason that your script failed is in some other place.

    Let's start with the formula you used to create the key:

    use="substring(concat(currentDate, @createDate), 1,7)"
    

    As I see, you:

    • Concatenate child element currentDate and attribute createDate (I assume they are 2 dates formatted as yyyy-mm-dd).
    • Take first seven chars of the above string.

    So the final result is yyyy-mm part of currentDate (only). Are you sure that this is correct? Why do you "add" createDate? Nothing from it is the part of the final substring.

    Note that in my script I took only a single date - createDate attribute. If my choice is wrong, then change createDate to currentDate in both the script and the source XML.

    Another, maybe more important, problem with your script is that you used $monthNames[position()=$MonthBlog] which (at least under xsltransform) generates error message: Cannot compare xs:integer to xs:string.

    The reason is that $MonthBlog is a string, but the required type to compare with position() is integer. In my script I used $monthNames[number($MonthBlog)], as you can see, applying the proper conversion and without (in this case default) position().

    And the last important issue: You didn't specify the version of XSLT, so I used version 2.0.

    So to sum up: Compare my working script with yours, maybe you will find some errors in your script.

    Edit

    I prepared another script, in version 1.0, see http://xsltransform.net/pNvs5vT/1.

    Key differences:

    1. Version 1.0 does not accept such constructs as sequence of strings (like ('January','February',...)), so I used a sequence of child nodes instead.

    2. The content of this variable is of Result Tree Fragment type, so to allow to use it in XPath expressions, I had to use exsl:node-set function. This in turn required to put extra stuff in transform tag and causes that this script does not work under 2.0 version any more.

    3. In template matching root I used Muenchian grouping to output li and a tags only for the first blog from each month, and deleted printing of id and createDate from the current Blog element.