Copied to clipboard

Flag this post as spam?

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


  • Eric Boen 40 posts 64 karma points
    Aug 08, 2010 @ 17:19
    Eric Boen
    0

    for-each and previous node comparison

    Hi,

    What I need to do is sort a Media folder of documents by a custom property call dateGenerated.  I've sorted the list in descending order and would like to list it out and demarkate the list by years.  In order to do this I need to compare the last item in the sorted for-each with the current item and if the year does not match then print out the year label.  I've been unable to make any headway on this as it is sorted so using xslt siblings is grabbing the non sorted node.  Any help would be greatly appretiated.

    <xsl:template match="/">
    <xsl:variable name="myNodes" select="umbraco.library:GetMedia(1216,'true')/descendant-or-self::*[@nodeTypeAlias='File']" />
    <ul id="docList">
      <xsl:for-each select="$myNodes">
      <xsl:sort select="./dateGenerated" order="descending" />
      

      <xsl:variable name="thisYear" select="umbraco.library:FormatDateTime(./dateGenerated, 'yyyy')"/>
      <xsl:variable name="thisMonth" select="umbraco.library:FormatDateTime(./dateGenerated, 'MMMM')"/>
     

       <!-- I would like to compare the previous node year with the current so I can print out a new year header -->

       <li>  
        <a href="{./umbracoFile}" target="_blank">
          <xsl:value-of select="$thisMonth"/>
        </a>
      </li>
      </xsl:for-each>
    </ul>
    </xsl:template>

    Desired output

    2010

    August Financials

    April Financials

    February Financials

    2009

    December Financials

    September Financials

    May Financials

    2008

    etc etc

    Thanks


    Eric

  • Matt Brailsford 2279 posts 11088 karma points MVP 6x c-trib
    Aug 08, 2010 @ 17:28
    Matt Brailsford
    0

    Hey Eric,

    You'll want to look into the preceding-sibling::* axis.

    Off the top of my head, something like this should work

    <xsl:if test="position() = 1 or umbraco.library:FormatDateTime(preceding-sibling::*/dateGenerated, 'yyyy') != $thisYear">
    <h1><xsl:value-of select="$thisYear"/></h1>
    </xsl:if>

    Matt

  • Chriztian Steinmeier 2698 posts 8108 karma points MVP 3x admin c-trib
    Aug 08, 2010 @ 18:49
    Chriztian Steinmeier
    0

    Hi Eric,

    You're right - you can't use the *-sibling:: axes when you're sorting, because they always work on document order. What you need to do, is to search the forum (and maybe Google) for "XSLT grouping" and you should probably look into a technique called "Muenchian Grouping" - I'll cook up an example for you if you like, but first I'll need to ask about the months: Are you going to group by month too or will there only be a single node (i.e., "April Financials") for each month?

    /Chriztian

  • Eric Boen 40 posts 64 karma points
    Aug 08, 2010 @ 18:51
    Eric Boen
    0

    Hi,

    This doesn't work as preceding-sibling is giving me the previous node in the unsorted.  I need to get the previous node in my sorted list. 

    @Matt BTW - I just started using the Desktop Media Upload....very nice tool.

    Eric

  • Matt Brailsford 2279 posts 11088 karma points MVP 6x c-trib
    Aug 08, 2010 @ 19:01
    Matt Brailsford
    0

    Hey Eric,

    You could always sort the nodes, store them in a var and then loop through that nodeset using the preceding-sibling method (I'm sure Chriztian will come up with some killer one liner though ;) )

    Glad you're liking DMU

    Matt

  • Chriztian Steinmeier 2698 posts 8108 karma points MVP 3x admin c-trib
    Aug 09, 2010 @ 01:09
    Chriztian Steinmeier
    1

    @Matt: HA :-) Tough one, though, technically it's possible (most XSLT should work fine collapsed to a single line) but doesn't really count :-)

    @Eric: Here's a "textbook" Muenchian Grouping example:

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:umbraco.library="urn:umbraco.library"
        exclude-result-prefixes="umbraco.library"
    >
        <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
    
        <xsl:param name="currentPage" />
    
        <xsl:variable name="myNodes" select="umbraco.library:GetMedia(1216, true())/descendant-or-self::*[@nodeTypeAlias = 'File']" />
    
        <!-- Create a key (index) on File elements indexed by year -->
        <xsl:key name="file-by-year" match="*[@nodeTypeAlias = 'File']" use="substring(dateGenerated, 1, 4)" />
    
        <xsl:template match="/">
            <!-- This finds the first node in every year group -->
            <xsl:for-each select="$myNodes[count(. | key('file-by-year', substring(dateGenerated, 1, 4))[1]) = 1]">
                <xsl:sort select="dateGenerated" order="descending" />
    
                <!-- Process the once-per-group info (i.e., write the header) -->
                <xsl:apply-templates select="." mode="group" />
    
                <ul>
                    <!-- Process each item in this group -->
                    <xsl:apply-templates select="key('file-by-year', substring(dateGenerated, 1, 4))" mode="item">
                        <xsl:sort select="dateGenerated" order="descending" />
                    </xsl:apply-templates>
                </ul>
            </xsl:for-each>
        </xsl:template>
    
        <!-- Output for group header (applied once per group) -->
        <xsl:template match="*[@nodeTypeAlias = 'File']" mode="group">
            <h2>
                <xsl:value-of select="substring(dateGenerated, 1, 4)" />
            </h2>
        </xsl:template>
    
        <!-- Output for each item in the group -->
        <xsl:template match="*[@nodeTypeAlias = 'File']" mode="item">
            <li>
                <a href="{umbracoFile}" title="{umbracoFile}" target="_blank">
                    <xsl:value-of select="umbracoFile" />
                </a>
            </li>
        </xsl:template>
    
    </xsl:stylesheet>

    /Chriztian

  • Eric Boen 40 posts 64 karma points
    Aug 09, 2010 @ 04:09
    Eric Boen
    0

    @Chriztian - Impressive, works like a charm.  I had already made a user control to do the same thing once I had enough of trying to get it to work in xsl. This is a sweet way of grouping.  I'm going to replace my user control with this snazzy little piece of code.

    Thanks

    Eric

  • Chriztian Steinmeier 2698 posts 8108 karma points MVP 3x admin c-trib
    Aug 09, 2010 @ 09:28
    Chriztian Steinmeier
    0

    Great! I guess that's 1-0 to XSLT, then :-)

    /Chriztian

  • Matt Brailsford 2279 posts 11088 karma points MVP 6x c-trib
    Aug 09, 2010 @ 09:34
    Matt Brailsford
    0

    Sweet. This is why I love trying to answer the XSLT questions, you can rest assured Chriztian will come in with a stonker =)

    Awesome example

    Matt

Please Sign in or register to post replies

Write your reply to:

Draft