Copied to clipboard

Flag this post as spam?

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


  • Dan 1288 posts 3921 karma points c-trib
    Mar 24, 2010 @ 16:30
    Dan
    0

    Get property of sibling within loop

    Hi,

    I'm trying to list a series of article pages, under their relevant month headings.  Having read elsewhere that XSLT grouping is a little tricky, I'm opting for the simpler approach of just looping through the articles (ordered by date) and getting the month name of the current article and the month name of the preceding sibling article, and if they're different, writing out the month as a header.  This should then format all of my articles under their relevant month heading.

    However, the bit of code I'm using to get the month name of the sibling article isn't working:

    <xsl:variable name="lastMonth" select="preceding-sibling::data[umbraco.library:FormatDateTime(data [@alias='eventDate'],'MMMM')]" />

    <!--I've also tried:
    <xsl:variable name="lastMonth" select="preceding-sibling::node[umbraco.library:FormatDateTime(data [@alias='eventDate'],'MMMM')]" />
    -->

    I've looked in the wiki but this area isn't covered yet.  Can anyone tell my what's wrong with the above code?

    Thanks!

  • Dan 1288 posts 3921 karma points c-trib
    Mar 24, 2010 @ 16:31
    Dan
    0

    The wiki article I'm taking about is this one, by the way: http://umbraco.org/documentation/books/xslt-basics/xpath-axes-and-their-shortcuts.

  • webangelo 107 posts 190 karma points
    Mar 24, 2010 @ 18:19
    webangelo
    0

    Hey dan,

    A couple of things.  First, you probably need to use the library function around the whole result, not just the data portion.

    Another possibility is the fact that the preceding-sibling call actually gets you all preceding siblings.  I believe preceding-siblings does get them in reverse order, so you would likely want the first one. So try something like:

    <xsl:variable name="lastMonth" select="umbraco.library:FormatDateTime(preceding-sibling::node[1]/data [@alias='eventDate'],'MMMM')" />

     

  • Dan 1288 posts 3921 karma points c-trib
    Mar 24, 2010 @ 18:38
    Dan
    0

    Thanks webangelo, that's brought me a step nearer, but it still doesn't seem to be behaving as it should.  The full code I have is essentially this:

    <ul>
    <xsl:for-each select="$currentPage/descendant::node [@level=$level]">
    <xsl:sort select="data [@alias = 'eventDate']" order="descending" />
    <xsl:variable name="eventTeaser" select="data [@alias='eventTeaser']"/>
    <xsl:variable name="thisMonth" select="umbraco.library:FormatDateTime(data [@alias='eventDate'],'MMMM')" />
    <xsl:variable name="lastMonth" select="umbraco.library:FormatDateTime(preceding-sibling::node[1]/data [@alias='eventDate'],'MMMM')" />
    <!--Output values of current month to check what's going on-->
    <p>Current month: <xsl:value-of select="$thisMonth"/></p>
    <p>Last month: <xsl:value-of select="$lastMonth"/></p>
    <xsl:if test="$thisMonth != $lastMonth">
    <h2><xsl:value-of select="$thisMonth" /></h2>
    </xsl:if>
    <xsl:value-of select="$thisMonth" />
    </xsl:for-each>
    </ul>

    There are 6 articles in my site - 5 in April and 1 in March, so I'd expect the output to be like this:

    <ul>
    <h2>April</h2>
    <li>Test event 1</li>
    <li>Test event 2</li>
    <li>Test event 3</li>
    <li>Test event 4</li>
    <li>Test event 5</li>
    <h2>March</h2>
    <li>Test event 6</li>
    </ul>

     

    However, it's actually doing this:

    <ul>
    <h2>April</h2>
    <h2>April</h2>
    <h2>April</h2>
    <h2>April</h2>
    <h2>April</h2>
    <h2>March</h2>
    <li>Test event 1</li>
    <li>Test event 2</li>
    <li>Test event 3</li>
    <li>Test event 4</li>
    <li>Test event 5</li>
    <li>Test event 6</li>
    </ul>

    Any ideas would be greatly appreciated, thanks!

  • Dan 1288 posts 3921 karma points c-trib
    Mar 24, 2010 @ 18:39
    Dan
    0

    Sorry that first block should be:

    <ul>
           
    <xsl:for-each select="$currentPage/descendant::node [@level=$level]">
                   
    <xsl:sort select="data [@alias = 'eventDate']" order="descending" />
                   
    <xsl:variable name="eventTeaser" select="data [@alias='eventTeaser']"/>
                   
    <xsl:variable name="thisMonth" select="umbraco.library:FormatDateTime(data [@alias='eventDate'],'MMMM')" />
                   
    <xsl:variable name="lastMonth" select="umbraco.library:FormatDateTime(preceding-sibling::node[1]/data [@alias='eventDate'],'MMMM')" />
                   
    <!--Output values of current month to check what's going on-->
                   
    <p>Current month: <xsl:value-of select="$thisMonth"/></p>
                   
    <p>Last month: <xsl:value-of select="$lastMonth"/></p>
                   
    <xsl:if test="$thisMonth != $lastMonth">
                           
    <h2><xsl:value-of select="$thisMonth" /></h2>
                   
    </xsl:if>
                   
    <li><xsl:value-of select="$eventTeaser" /></li>
           
    </xsl:for-each>
    </ul>
  • Dan 1288 posts 3921 karma points c-trib
    Mar 24, 2010 @ 18:48
    Dan
    0

    The exact output, with the current and last month values, in case it's useful is:

    <ul>
            <p>Current month: April</p>
            <p>Last month:</p>
            <h2>April</h2>
            <p>Current month: April</p>
            <p>Last month:</p>
            <h2>April</h2>
            <p>Current month: April</p>
            <p>Last month:</p>
            <h2>April</h2>
            <p>Current month: April</p>
            <p>Last month: April</p>
            <h2>April</h2>
            <p>Current month: April</p>
            <p>Last month: April</p>
            <h2>April</h2>
            <p>Current month: March</p>
            <p>Last month: April</p>
            <h2>March</h2>
           
    <li>Test event 1</li>
           
    <li>Test event 2</li>
           
    <li>Test event 3</li>
           
    <li>Test event 4</li>  
           
    <li>Test event 5</li>
           
    <li>Test event 6</li>
    </ul>

    So it's clearly putting the h2 tags in where it sees fit, but it's just not getting the previous sibling correctly to set a correct value for lastMonth.

  • webangelo 107 posts 190 karma points
    Mar 24, 2010 @ 21:08
    webangelo
    0

    Ahhh yes.  Even though you are getting the in sorted order, the tree it is checking for siblings is still in its original order.  Try doing this before your for-each:

    <xsl:variable name="sortedNodes">
    <xsl:for-each select="$currentPage/ancestor-or-self::node/node">
               <xsl:sort select="data [@alias = 'eventDate']" order="descending" />
        <xsl:copy-of select="." />
    </xsl:for-each>
    </xsl:variable>

    And for your for-each try:

    <xsl:for-each select="msxml:node-set($sortedNodes)/node">

     

  • Dan 1288 posts 3921 karma points c-trib
    Mar 25, 2010 @ 10:24
    Dan
    0

    That's great, thanks!  I modified slightly, so for future reference I updated the code above to:

    <xsl:variable name="sortedNodes">
    <xsl:for-each select="$currentPage/descendant::node [@level=$level]">
    <xsl:sort select="data [@alias = 'eventDate']" order="descending" />
    <xsl:copy-of select="." />
    </xsl:for-each>
    </xsl:variable>
  • Dan 1288 posts 3921 karma points c-trib
    Mar 25, 2010 @ 10:44
    Dan
    0

    Actually, I also need to get a value from the parent node within the loop, but this isn't working as I would have expected.  Here's what I'm doing:

    <xsl:variable name="sortedNodes">
    <xsl:for-each select="$currentPage/descendant::node [@level=$level]">
               
    <xsl:sort select="data [@alias = 'eventDate']" order="descending" />
       
    <xsl:copy-of select="." />
    </xsl:for-each>
    </xsl:variable>

    <ul>
           

    <xsl:for-each select="msxml:node-set($sortedNodes)/node">
    <xsl:variable name="projectColour" select="string(../data [@alias = 'projectColour'])"/>
                    <xsl:variable name="eventTeaser" select="data [@alias='eventTeaser']"/>
                   
    <xsl:variable name="thisMonth" select="umbraco.library:FormatDateTime(data [@alias='eventDate'],'MMMM')" />
                   
    <xsl:variable name="lastMonth" select="umbraco.library:FormatDateTime(preceding-sibling::node[1]/data [@alias='eventDate'],'MMMM')" />
                   
    <!--Output values of current month to check what's going on-->
                   
    <p>Current month: <xsl:value-of select="$thisMonth"/></p>
                   
    <p>Last month: <xsl:value-of select="$lastMonth"/></p>
                   
    <xsl:if test="$thisMonth != $lastMonth">
                           
    <h2><xsl:value-of select="$thisMonth" /></h2>
                   
    </xsl:if>
                   
    <li>
    <p>Teaser: <xsl:value-of
    select="$eventTeaser" /></p>
    <p>Colour:
    <xsl:value-of select="$projectColour" /></p>
    </li>

           
    </xsl:for-each>
    </ul>

    It doesn't seem to pick up anything for the 'projectColour' - the rest works fine.  How do I access data from the parent node when using this method?

    Thanks

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Mar 25, 2010 @ 11:41
    Chriztian Steinmeier
    1

    Hi - Dan,

    Since you've limited the node context to the node-set created in the sortedNodes variable, you'll need to grab the wanted item using the original context - try this:

    <xsl:variable name="projectColour" select="umbraco.library:GetXmlNodeById(@id)/../data[@alias = 'projectColour']" />

    If that doesn't work (bet you it does, though) you can pull in the context from $currentPage:

    <xsl:variable name="projectColour" select="$currentPage/ancestor-or-self::node[@level = 1]//node[@id = current()/@id]/../data[@alias = 'projectColour']" />

    /Chriztian 

  • Dan 1288 posts 3921 karma points c-trib
    Mar 25, 2010 @ 12:03
    Dan
    0

    The first one worked perfectly, thanks Chriztian.  I'm sorry I can't mark your post as solved - but I've voted it up anyhow.  Much appreciated.

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Mar 25, 2010 @ 12:18
    Chriztian Steinmeier
    0

    No worries - it's not "all about the money", you know :-)

    /Chriztian

Please Sign in or register to post replies

Write your reply to:

Draft