Copied to clipboard

Flag this post as spam?

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


  • Alexandru 112 posts 272 karma points
    Oct 30, 2013 @ 12:05
    Alexandru
    0

    Using a key

    Hello,

    I am trying to use a key in order to only display posts from distinct authors on the homepage of my blog.

    This is how I do it and it works peorperly:

          <xsl:key  name="MyKey" match="umbBlogPost" use="@creatorName"/>
    
    <xsl:for-each select="$currentPage/ancestor-or-self::umbBlog//umbBlogPost[generate-id() = generate-id(key('MyKey', @creatorName)[1])]">
        <xsl:sort select="./PostDate" order="descending" />
                <xsl:if test="position() &lt;= $numberOfPosts">                 
                    <xsl:call-template name="showpost">
                        <xsl:with-param name="post" select="."/>
                    </xsl:call-template>
                </xsl:if>
      </xsl:for-each>
    

    The problem is: I would like to display the LATEST posts from the authors, not the oldest ones.

    Any suggestions?

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Oct 30, 2013 @ 12:13
    Chriztian Steinmeier
    0

    Hi Alexandru,

    Which format is the PostDate property? Could it be cased wrong? (E.g.: Usually, if you enter "Post Date" as the property name, the alias will be "postDate").

    /Chriztian

  • Alexandru 112 posts 272 karma points
    Oct 30, 2013 @ 12:22
    Alexandru
    0

    enter image description here

    The problem is not there, that part of the code works fine.

    The problem is that the posts get filtered for a unique author before they are being sorted by the post date. The very first posts of the authors make it through the filter and THEN, they are being sorted - which is not very helpful.

    I need to first sort ALL posts by the date and THEN filter out the posts with distinct authors.

    Do I make sense?

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Oct 30, 2013 @ 12:47
    Chriztian Steinmeier
    1

    Ha - yes, of course :-)

    Okay - that's a good challenge... I'd say something like this should do it:

    <xsl:key name="PostByCreator" match="umbBlogPost" use="@creatorName" />
    
    <xsl:variable name="blogRoot" select="$currentPage/ancestor-or-self::umbBlog" />
    
    <xsl:for-each select="$blogRoot//umbBlogPost[generate-id() = generate-id(key('PostByCreator', @creatorName)[1])]">
        <xsl:sort select="PostDate" order="descending" />
        <xsl:if test="position() &lt;= $numberOfPosts">
            <!-- Find all the current author's posts - ordered by date descending -->
            <xsl:for-each select="key('PostByCreator', @creatorName)">
                <xsl:sort select="PostDate" order="descending" />
                <!-- Display the latest -->
                <xsl:if test="position() = 1">
                    <xsl:call-template name="showpost">
                        <xsl:with-param name="post" select="."/>
                    </xsl:call-template>
                </xsl:if>
            </xsl:for-each>
        </xsl:if>
    </xsl:for-each>
    

    /Chriztian

  • Alexandru 112 posts 272 karma points
    Oct 30, 2013 @ 13:03
    Alexandru
    0

    Looks good, it works. But when new posts appear, they don't go on top of the page, they just replace the previous post from that author. I shall try something out...

  • Alexandru 112 posts 272 karma points
    Oct 30, 2013 @ 13:07
    Alexandru
    0

    For example:

    I have 3 authors.

    Your solution would have their latest posts printed out this order:

    • Author3
    • Author2
    • Author1

    When author 1 writes a new post, the order on the homepage will still be like this:

    • author3
    • author2
    • author1

    I need it to be like this:

    • Author1
    • Author3
    • Author2

    Makes sense? :)

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Oct 30, 2013 @ 14:24
    Chriztian Steinmeier
    0

    Hi Alexandru,

    Yeah - I was going to put a line in about the way you'd sort the authors at first, but didn't bother - e.g., when you have 10 unique authors, but only showing a max. of 5 posts - that wouldn't go on right...

    I think you need to build an intermediate result of all the authors' latest post, and then display the latest X of those:

    <xsl:key name="CreatorByName" match="@creatorName" use="." />
    <xsl:key name="PostByCreator" match="umbBlogPost" use="@creatorName" />
    
    <xsl:variable name="blogRoot" select="$currentPage/ancestor-or-self::umbBlog" />
    
    <!-- Collect the latest post by each individual author -->
    <xsl:variable name="latestPostByCreatorProxy">
        <xsl:for-each select="$blogRoot//umbBlogPost/@creatorName[generate-id() = generate-id(key('CreatorByName', .)[1])]">
            <xsl:for-each select="key('PostByCreator', .)">
                <xsl:sort select="PostDate" data-type="text" order="descending" />
                <!-- Store a reference to the latest post by this author -->
                <xsl:if test="position() = 1">
                    <post id="{@id}" creatorName="{@creatorName}" postDate="{PostDate}" />
                </xsl:if>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:variable>
    <xsl:variable name="latestPostByCreator" select="msxsl:node-set($latestPostByCreatorProxy)" />
    
    <!-- Display the posts by grabbing the real nodes by id -->
    <xsl:for-each select="$latestPostByCreator/post">
        <xsl:sort select="@postDate" data-type="text" order="descending" />
        <xsl:call-template name="showpost">
            <xsl:with-param name="post" select="$blogRoot//umbBlogPost[@id = current()/@id]" />
        </xsl:call-template>
    </xsl:for-each>
    

    Let me know id it works at all :-)

    /Chriztian

  • Alexandru 112 posts 272 karma points
    Nov 01, 2013 @ 08:30
    Alexandru
    0

    Hi, thanks for this, I shall try it out now as I have been away from the office yesterday. I'll get back to you with a result!

  • Alexandru 112 posts 272 karma points
    Nov 01, 2013 @ 09:12
    Alexandru
    0

    I seem to be getting only one post from one author so far...

    I can't figure out where it goes wrong. I think it only loops once through the first for-each loop

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Nov 01, 2013 @ 10:27
    Chriztian Steinmeier
    0

    Hmm - I have this (isolated example) working correct here, so would maybe need to check if outer circumstances could be affecting it?

    /Chriztian

  • Alexandru 112 posts 272 karma points
    Nov 04, 2013 @ 09:25
    Alexandru
    0

    I have gone over it many times by now and I can not find any outer circumstances that affect it.

    The code you showed definitely makes sense but I have no idea why it would not work. I have tried making changes to it, but anything I do leads to nonsense display on the homepage which is nowhere near what I want to display.

    Is there any other way around this?

  • Alexandru 112 posts 272 karma points
    Nov 06, 2013 @ 09:16
    Alexandru
    0

    Tthis is the closest I have got so far... The correct posts show but they repeat just as many times as the number of posts from that author.

    I have 3 authors at the moment (A1 has 10 posts, A2 has 2 posts and A3 has 1 post) and right now my homapage looks like this: - 10x latest post from A1 - 2x latest post from A2 - 3x latest post from A3

    This is the code:

    <xsl:key name="CreatorByName" match="@creatorName" use="." />
      <xsl:key name="PostByCreator" match="umbBlogPost" use="@creatorName" />
      <xsl:variable name="blogRoot" select="$currentPage/ancestor-or-self::umbBlog" />
    <xsl:variable name="latestPostByCreatorProxy">
    <xsl:for-each select="$blogRoot//umbBlogPost/@creatorName">
        <xsl:for-each select="key('PostByCreator', .)">  <!-- MAKE IT LOOP ONLY ONCE -->
            <xsl:sort select="PostDate" order="descending" />
                <xsl:if test="position() = 1"> 
                    <post id="{@id}" creatorName="{@creatorName}" postDate="{PostDate}" />
                </xsl:if>
        </xsl:for-each>
    </xsl:for-each>
    

    <xsl:for-each select="$latestPostByCreator/post">
        <xsl:sort select="@postDate" data-type="text" order="descending" />
        <xsl:call-template name="showpost">
            <xsl:with-param name="post" select="$blogRoot//umbBlogPost[@id = current()/@id]" />
        </xsl:call-template>
    </xsl:for-each>
    

    I think the inner foreach loop from the proxy should only loop once but I have no idea how to make it do that... Alo, all posts have some javascript, however, whichever post I click, it triggers the script from the first one.

    Please help me out a bit on this, I can feel I am so close...

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Nov 06, 2013 @ 09:42
    Chriztian Steinmeier
    0

    Hi Alexandru,

    At the point where you say "MAKE IT LOOP ONLY ONCE" it actually needs to take all the creator's posts, because we need to sort them to be able to get the 1st one (i.e., the latest).

    Could you try to dump the contents of the $latestPostByCreator variable after its created? Like this:

    <textarea><xsl:copy-of select="$latestPostByCreator" /></textarea>
    

    This should hold a single <post> element for each creator...

    /Chriztian

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Nov 06, 2013 @ 09:45
    Chriztian Steinmeier
    0

    I can see the <for-each> just above the "MAKE IT LOOP..." comment has been changed from my example - that's where you need to do the key() + generate-id() thing, to make sure we only run through unique @creatorName attributes...

  • Alexandru 112 posts 272 karma points
    Nov 06, 2013 @ 09:50
    Alexandru
    0

    I dumped it all in a textarea and it shows many copies of the latest post, just like my homepage currently does.

    I had fiddled with your example, yes trying to figure out where could the problem be. If I use the example exactly as you gave it, i would only get only the post from the author that has one post.

  • Alexandru 112 posts 272 karma points
    Nov 06, 2013 @ 09:55
    Alexandru
    0

    This is how your example looks like with the variable dumped into a textarea:

    enter image description here

    Also, I get the same post 3 times on 3 different pages - as you can see I swap to pages with older posts where the same post shows up. I have done it so you can only swap to older posts IF there are more than 5 posts on the page.

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Nov 06, 2013 @ 10:12
    Chriztian Steinmeier
    0

    Alright,

    I'd love to help you out - but I think I need to look at the full XSLT file now, to get an idea.

    Feel free to email me at chriztian @ steinmeier [dot] dk, if it's not super-sensitive client stuff that you've signed several NDA's for :-)

    We can post the final solution(s) here again when finished so others don't get here in vain...

    /Chriztian

  • Alexandru 112 posts 272 karma points
    Nov 06, 2013 @ 10:24
    Alexandru
    0

    Okay, I have sent you an email :)

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Nov 07, 2013 @ 10:30
    Chriztian Steinmeier
    100

    So we found a solution - the problem was that selecting attributes with a key() and using generate-id() for those didn't produce predictable results.

    Changing to use the PostByCreator key instead (which selects elements instead of attributes) made it work as intended - so here's the final changed section that creates an XML variable with the latest post by each individual author (only lines 2 + 3 were changed):

    <xsl:variable name="latestPostByCreatorProxy">
        <xsl:for-each select="$blogRoot//umbBlogPost[generate-id() = generate-id(key('PostByCreator', @creatorName)[1])]">
            <xsl:for-each select="key('PostByCreator', @creatorName)"> 
                <xsl:sort select="PostDate" order="descending" />
                <xsl:if test="position() = 1"> 
                <post id="{@id}" creatorName="{@creatorName}" postDate="{PostDate}" />
            </xsl:if>
            </xsl:for-each>
        </xsl:for-each>
    </xsl:variable>
    <xsl:variable name="latestPostByCreator" select="msxsl:node-set($latestPostByCreatorProxy)" />
    

    /Chriztian

  • Alexandru 112 posts 272 karma points
    Nov 07, 2013 @ 10:34
    Alexandru
    0

    Thank you so much for this!

    Have a good day!

  • Alexandru 112 posts 272 karma points
    Dec 09, 2013 @ 12:18
    Alexandru
    0

    Chriztian,

    I have come across a new issue with this and I was hoping I could get your help again as I can't seem to fix it myself.

    My blog now supports scheduled posts which means that you can publish posts with a future date and this messes up the way my homepage works.

    What I need to do is add a filter that only looks through posts that fit this condition:

    umbraco.library:DateDiff(PostDate, $currentDate, 's') &lt;= 0
    

    I have tried adding this condition to the first foreach predicate in the above code but it didn't work. Any ideas why?

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Dec 09, 2013 @ 13:11
    Chriztian Steinmeier
    1

    Hi Alexandru,

    You would want to add that condition where you're running through each author's posts, i.e. in the second for-each of the variable:

    <xsl:for-each select="key('PostByCreator', @creatorName)[ADD CONDITION HERE]"> 
        <xsl:sort select="PostDate" order="descending" />
        <xsl:if test="position() = 1"> 
            <post id="{@id}" creatorName="{@creatorName}" postDate="{PostDate}" />
        </xsl:if>
    </xsl:for-each>
    

    /Chriztian

  • Alexandru 112 posts 272 karma points
    Dec 10, 2013 @ 09:29
    Alexandru
    0

    Aye, thanks!

Please Sign in or register to post replies

Write your reply to:

Draft