Copied to clipboard

Flag this post as spam?

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


  • syn-rg 282 posts 425 karma points
    Oct 26, 2012 @ 04:33
    syn-rg
    0

    How to display number of new child pages XSLT

    I have two separate pieces of code I'm trying to combine.

    The first counts the number of child pages and displays a number:

    e.g. 8 child pages (or child page, if only 1 page)

    <xsl:choose>
    <xsl:when test="count(child::DocTypeAlias) &gt; 1">
        <p><xsl:value-of select="count(child::DocTypeAlias)"/> child pages</p>
    </xsl:when>
    <xsl:otherwise>
        <p><xsl:value-of select="count(child::DocTypeAlias)"/> child page</p>
    </xsl:otherwise>

     

    The code detects if the page was created within the last 30 days:

    <xsl:variable name="datediff" select="umbraco.library:DateDiff(umbraco.library:ShortDate(umbraco.library:CurrentDate()), umbraco.library:ShortDate(@createDate), 'm')" />
        <xsl:if test="$datediff &lt; (1440 * 30)">
            <p>New</p>
        </xsl:if>

    I want to combine them so I can get a count of child pages and a count of the "new" pages.

    e.g. 8 child pages - 2 new pages

    I've tried the following but it doesn't return the correct values:

    <xsl:variable name="datediff" select="umbraco.library:DateDiff(umbraco.library:ShortDate(umbraco.library:CurrentDate()), umbraco.library:ShortDate(@createDate), 'm')" />
        <xsl:choose>
            <xsl:when test="$datediff &lt; (1440 * 30) and count(child::DocTypeAlias) &gt; 1">
                <p><xsl:value-of select="$datediff &lt; (1440 * 30) and count(child::DocTypeAlias)"/> new pages</p>
            </xsl:when>
            <xsl:otherwise>
                <p><xsl:value-of select="$datediff &lt; (1440 * 30) and count(child::DocTypeAlias)"/> new page</p>
            </xsl:otherwise>
        </xsl:choose>

    It returns: "true new pages" I don't know how to get it to display the number (2 new pages).

    Can anyone help? Cheers, JV

  • Steve G 2 posts 22 karma points
    Oct 26, 2012 @ 16:57
    Steve G
    0

    I'm fairly new to XSLT but the reason I can see that you get "true new pages" is that you are asking for the value of a 'binary and' condition which equates to 'true'.  I'm not in a position to test this but I'd expect to see something like:

    <xsl:variable name="datediff" select="umbraco.library:DateDiff(umbraco.library:ShortDate(umbraco.library:CurrentDate()), umbraco.library:ShortDate(@createDate), 'm')" />
    <xsl:choose>
    <xsl:when test="$datediff &lt; (1440 * 30) and count(child::DocTypeAlias) &gt; 1">
    <p><xsl:value-of select="$datediff &lt; (1440 * 30)"><xsl:value-of select="count(child::DocTypeAlias)"/> new pages</xsl:value-of></p>
    </xsl:when>
    <xsl:otherwise>
    <p><xsl:value-of select="$datediff &lt; (1440 * 30)"><xsl:value-of select="count(child::DocTypeAlias)"/> new page</xsl:value-of></p>
    </xsl:otherwise>
    </xsl:choose>


  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Oct 26, 2012 @ 21:36
    Chriztian Steinmeier
    1

    Hi JV,

    Steve is right, you ask for the value of a boolean test, so you're getting 'true' as output. Here's a simpler way to do it - note that I use variables extensively, which should make it easier for anyone reading it to grasp what's going on, but also to not be calling the extension methods more than once:

    <!-- The date calculation stuff -->
    <xsl:variable name="today" select="umb:CurrentDate()" />
    <xsl:variable name="oneMonthAgo" select="umb:DateAdd($today, 'm', -1)" />
    
    <!-- Grab the nodes to look at -->
    <xsl:variable name="nodes" select="$currentPage/DocTypeAlias" />
    
    <!-- Pages created within the last 30 days -->
    <xsl:variable name="newPages" select="$nodes[umb:DateGreaterThanOrEqual(@createDate, $oneMonthAgo)]" />
    
    <xsl:template match="/">
        <p>
            <xsl:value-of select="count($newPages)" />
            <xsl:text> new page</xsl:text>
            <xsl:if test="count($newPages) &gt; 1">s</xsl:if>
        </p>
    </xsl:template>
    

    /Chriztian 

  • syn-rg 282 posts 425 karma points
    Oct 29, 2012 @ 01:53
    syn-rg
    0

    Thanks Chriztian, that works really well.

    How would I be able to do the same for "grandchild" nodes?

    I've tried the following but it pulls in all descendants:

    <xsl:variable name="nodes" select="$currentPage//DocTypeAlias" />
  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Oct 29, 2012 @ 08:21
    Chriztian Steinmeier
    0

    Hi JV,

    With XPath there's usually more than one solution, depending on how specific you want to be - simplest thing would be:

    <xsl:variable name="nodes" select="$currentPage/*/DocTypeAlias" />

    /Chriztian

  • syn-rg 282 posts 425 karma points
    Oct 29, 2012 @ 23:40
    syn-rg
    0

    Hi Chriztian,

    I've tried that, but it's pulling in all the descendants too.

    These both result in the following example:

    <xsl:variablename="nodes"select="$currentPage//DocTypeAlias"/>
    <xsl:variablename="nodes"select="$currentPage/*/DocTypeAlias"/>

    e.g. Section 1 - 20 pages - 22 new pages, Section 2 -  2 pages - 22 new pages

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Oct 30, 2012 @ 21:01
    Chriztian Steinmeier
    0

    Hi JV,

    If those two give you the same result, all your "DocTypeAlias" pages are placed two levels down from $currentPage - that's just how it works.

    Did you use all of my code, or did you copy some of it? Note that I'm counting the $newPages variable, not the $nodes one...

    Another thing could be that all the pages were in fact created within the last month?

     

    Maybe you can share a little of the structure in Content to clear this up?

    /Chriztian 

  • syn-rg 282 posts 425 karma points
    Oct 31, 2012 @ 00:03
    syn-rg
    0

    Hi Chriztian,

    I'm using it for an Image Library I'm creating, the Content structure is as follows:

    Image Gallery
    Image Gallery Album
    Image Gallery Photo
    Image Gallery Photo
    Image Gallery Album
    Image Gallery Photo
    Image Gallery Photo

    The Image Gallery displays a list of the child Image Gallery Albums, and displays how many Image Gallery Photo's are within each album and how many new images.

     

    Below is the XSLT I'm using, I've copied your code but may not have it correct to allow for the split between New Images for each Image Gallery Album.

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]>
    <xsl:stylesheet 
        version="1.0" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
        xmlns:msxml="urn:schemas-microsoft-com:xslt" 
        xmlns:umbraco.library="urn:umbraco.library" xmlns:Exslt.ExsltCommon="urn:Exslt.ExsltCommon" xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes" xmlns:Exslt.ExsltMath="urn:Exslt.ExsltMath" xmlns:Exslt.ExsltRegularExpressions="urn:Exslt.ExsltRegularExpressions" xmlns:Exslt.ExsltStrings="urn:Exslt.ExsltStrings" xmlns:Exslt.ExsltSets="urn:Exslt.ExsltSets" xmlns:PS.XSLTsearch="urn:PS.XSLTsearch" 
        exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets PS.XSLTsearch ">
    
    <xsl:output method="xml" omit-xml-declaration="yes" />
    
    <xsl:param name="currentPage"/>
    
    <!-- Input the documenttype you want here -->
    <xsl:variable name="documentTypeAlias" select="string('ImageGalleryAlbum')"/> 
    
    <!-- The date calculation stuff -->
    <xsl:variable name="today" select="umbraco.library:CurrentDate()" />
    <xsl:variable name="oneMonthAgo" select="umbraco.library:DateAdd($today, 'd', -30)" />
    
    <!-- Grab the nodes to look at -->
    <xsl:variable name="nodes" select="$currentPage/*/ImageGalleryPhoto" />
    
    <!-- Pages created within the last 30 days -->
    <xsl:variable name="newPages" select="$nodes[umbraco.library:DateGreaterThanOrEqual(@createDate, $oneMonthAgo)]" />
    
    <xsl:template match="/">
    
    <!-- The fun starts here -->
        <div class="imageGalleryAlbum">
            <ul>
                <xsl:for-each select="$currentPage/* [name() = $documentTypeAlias and string(umbracoNaviHide) != '1']">
                    <li>
                        <xsl:if test="position() mod 4 &gt; 0">
                            <xsl:attribute name="class">image_1_3</xsl:attribute>
                        </xsl:if>
                        <xsl:if test="position() mod 4 = 0">
                            <xsl:attribute name="class">image_4</xsl:attribute>
                        </xsl:if>
                        <a href="{umbraco.library:NiceUrl(@id)}">
                            <img src="{concat(substring-before(umbraco.library:GetMedia(./*/imageGalleryPhoto, 'false')/umbracoFile,'.'), '_thumb_150.jpg')}" />
                        </a>
                        <p>
                            <a href="{umbraco.library:NiceUrl(@id)}">
                                <xsl:value-of select="@nodeName"/>
                            </a>
                        </p>
                        <xsl:choose>
                            <xsl:when test="count(child::ImageGalleryPhoto) &gt; 1">
                            <p><xsl:value-of select="count(child::ImageGalleryPhoto)"/> Images</p>
                            </xsl:when>
                            <xsl:otherwise>
                            <p><xsl:value-of select="count(child::ImageGalleryPhoto)"/> Image</p>
                            </xsl:otherwise>
                        </xsl:choose>
                        <xsl:choose>
                            <xsl:when test="count($newPages) &gt; 1">
                                <p>
                                    <xsl:value-of select="count($newPages)" />
                                    <xsl:text> New Image</xsl:text>
                                    <xsl:if test="count($newPages) &gt; 1">s</xsl:if>
                                </p>
                            </xsl:when>
                            <xsl:otherwise>
                            </xsl:otherwise>
                        </xsl:choose>
                    </li>
                </xsl:for-each>
            </ul>
        </div>
    
    </xsl:template>
    
    </xsl:stylesheet>
  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Oct 31, 2012 @ 00:18
    Chriztian Steinmeier
    0

    Ah yes, now I see :-)

    Yeah, you just need to filter the $newPages variable and only count the ones inside the current gallery - should be something like this:

    <!-- Select ImageGalleryPhoto children that also exist in the $newPages set -->
    <xsl:variable name="newImagesInHere" select="ImageGalleryPhoto[@id = $newPages/@id]" />
    <xsl:when test="$newImagesInHere">
        <p>
            <xsl:value-of select="count($newImagesInHere)" />
            <xsl:text> New Image</xsl:text>
            <xsl:if test="count($newImagesInHere) &gt; 1">s</xsl:if>
        </p>
    </xsl:when>

    (replaces last <xsl:when> block in your code)

    /Chriztian

  • syn-rg 282 posts 425 karma points
    Oct 31, 2012 @ 02:48
    syn-rg
    0

    Hi Chriztian,

    I just tried that code, and it didn't show any results.

    It would only show results when I changed it to this:

    <!-- Select ImageGalleryPhoto children that also exist in the $newPages set -->
    <xsl:variable name="newImagesInHere" select="$currentPage/*/ImageGalleryPhoto[@id = $newPages/@id]" />

    Which still gives me the total for all grandchildren. e.g. 22 New Images

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Oct 31, 2012 @ 08:59
    Chriztian Steinmeier
    1

    Hi JV,

    That seems strange, but let's get everything right then.

    I rewrote this to use a couple of match templates instead, which is much easier to manage (I think) and this gives me the right values for total and new images, when I recreate the structure you describe (these replace that one "the fun starts here" template):

    <xsl:template match="/">
        <div class="imageGalleryAlbum">
            <ul>
                <!-- Process albums below current page -->
                <xsl:apply-templates select="$currentPage/ImageGalleryAlbum[not(umbracoNaviHide = 1)]" />
            </ul>
        </div>
    </xsl:template>
    
    <xsl:template match="ImageGalleryAlbum">
        <li>
            <xsl:if test="position() mod 4 &gt; 0"><xsl:attribute name="class">image_1_3</xsl:attribute></xsl:if>
            <xsl:if test="position() mod 4 = 0"><xsl:attribute name="class">image_4</xsl:attribute></xsl:if>
            <a href="{umbraco.library:NiceUrl(@id)}">
                <!-- Create a thumbnail for the first ImageGalleryPhoto in here -->
                <xsl:apply-templates select="ImageGalleryPhoto[1]/imageGalleryPhoto[normalize-space()]" mode="thumb" />
            </a>
            <p>
                <a href="{umbraco.library:NiceUrl(@id)}">
                    <xsl:value-of select="@nodeName" />
                </a>
            </p>
    
            <p>
                <xsl:variable name="imagesInHere" select="count(ImageGalleryPhoto)" />
                <xsl:value-of select="$imagesInHere" />
                <xsl:text> Image</xsl:text>
                <xsl:if test="$imagesInHere &gt; 1">s</xsl:if>
            </p>
            <p>
                <xsl:variable name="newImagesInHere" select="count(ImageGalleryPhoto[@id = $newPages/@id])" />
                <xsl:value-of select="$newImagesInHere" />
                <xsl:text> New Image</xsl:text>
                <xsl:if test="$newImagesInHere &gt; 1">s</xsl:if>
            </p>
        </li>
    </xsl:template>
    
    <xsl:template match="*" mode="thumb">
        <xsl:variable name="media" select="umbraco.library:GetMedia(., false())" />
        <xsl:if test="not($media[error])">
            <xsl:variable name="extension" select="concat('.', $media/umbracoExtension)" />
            <img src="{concat(substring-before($media/umbracoFile, $extension), '_thumb_150.jpg')}" />
        </xsl:if>
    </xsl:template>
    

    /Chriztian

  • syn-rg 282 posts 425 karma points
    Nov 01, 2012 @ 00:28
    syn-rg
    0

    Thanks very much Chriztian! That works fantastically well. 

    I just made one very small edit, so that "New Images" will only display if there is more than 0 "New Images":

    <xsl:variable name="newImagesInHere" select="count(ImageGalleryPhoto[@id = $newPages/@id])" />
    <xsl:if test="$newImagesInHere &gt; 0">
    <p>
    <xsl:value-of select="$newImagesInHere" />
    <xsl:text> New Image</xsl:text>
    <xsl:if test="$newImagesInHere &gt; 1">s</xsl:if>
    </p>
    </xsl:if>

    Cheers!! JV

Please Sign in or register to post replies

Write your reply to:

Draft