Copied to clipboard

Flag this post as spam?

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


  • Claushingebjerg 939 posts 2574 karma points
    Apr 28, 2011 @ 08:54
    Claushingebjerg
    0

    sorting data from multiple external sources

    Im working on at site, where i need to list data from facebook updates, youtube rss, and umbraco.

    I've pretty much got it down to get the data from both sources by themselves.
    The problem is i need to sort them by date/time in between each other.
    And im a bit lost how to go about this.

    What im trying to achieve is something like this (simplified)

    <ul>
    <li>Youtube video from channel 01 - time10:38</li>
    <li>Facebook update from profile 02 - time10:55</li>
    <li>Facebook update from profile 01 - time11:01</li>
    <li>Facebook update from profile 01 - time11:04</li>
    <li>Umbraco News page - time11:15</li>
    <li>Youtube video from channel 02 - time11:30</li>
    <li>Youtube video from channel 01 - time12:30</li>
    </ul>

     

  • praveity 100 posts 125 karma points
    Apr 28, 2011 @ 13:39
    praveity
    0

    You could probably use the 

    <xsl:for-each select="your-condition">
    <xsl:sort select="substring(@sTime,7,4)" data-type="number"/>
    </xsl:for-each>

    where @sTime would be the date-time variable

    Remember: <xsl:sort/> must be always the first line within the <xsl:for-each/> if used.

  • Claushingebjerg 939 posts 2574 karma points
    Apr 28, 2011 @ 14:02
    Claushingebjerg
    0

    Cool... Any idea how to merge 2 or more sources, like 3 facebook status feeds and 2 youtube channels?

  • Tom Fulton 2030 posts 4998 karma points c-trib
    Apr 28, 2011 @ 14:23
    Tom Fulton
    0

    One thing you could do (there may be a better way) is to create a variable and add the nodes from each of the 3 feeds to it using a standard format, then do your for-each and sorting on that variable.

    Ex:

    <xsl:variable name="combinedFeeds">
     
    <nodes>
     
    <xsl:for-each select="$youTubeFeed/*">
       
    <node caption="./captionField"/>
     
    </xsl:for-each>
     
    <xsl:for-each select="$facebookFeed/*">
       
    <node caption="./captionField"/>
     
    </xsl:for-each>
     
    <xsl:for-each select="$currentPage/NewsItem">
       
    <node caption="./@nodeName"/>
     
    </xsl:for-each>
     
    </nodes>
    </xsl:variable>
    <xsl:for-each select="msxml:node-set($combinedFeeds)/*">
    <xsl:sort ...>
    </xsl:for-each>

    Not sure what the structure of the feeds are so obviously you'll need to adjust/add attributes or elements to each <node>, etc.

    Hope this helps,
    Tom

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Apr 28, 2011 @ 19:09
    Chriztian Steinmeier
    0

    Hi Claus (+ Tom),

    Actually, you can join all the nodes from various variables using a pipe character in a select, e.g.:

    <xsl:for-each select="$youTubeFeed | $facebookFeed | $currentPage/NewsItem">
        <xsl:sort ... />
        <!-- do stuff -->
    </xsl:for-each>

    But, you might need to get a little creative with the sort select, unless all sources have identical "datetime" data... 

    How do they look? 

    /Chriztian 

     

  • Claushingebjerg 939 posts 2574 karma points
    Jul 01, 2011 @ 22:27
    Claushingebjerg
    0

    Alright, so i kinda saw the light from your post there Chriztian, it helped a lot. But guess what, im stuck again :)

    I got it working by manually inputting the feed urls, but i would like to have the site editor be able to add feeds from the ui.

    I have a folder in the content node tree where the editor can create new "Feed" nodes with a text parameter "feedUrl" on the document type for inputting the url.

    As i see it, i need to:

    1. iterate through these nodes, and create variables from the "feedUrl" field.

    2. pass these variables to the <xsl:with-param

    But how do i go about these two steps?

    My current working code is below: 

     

    <?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.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes"
      exclude-result-prefixes="msxml umbraco.library Exslt.ExsltDatesAndTimes">

    <xsl:output method="xml" omit-xml-declaration="yes"/>

    <xsl:param name="currentPage"/>

    <xsl:template match="/">

      <xsl:variable name="feedContent"  select="umbraco.library:GetXmlDocumentByUrl('http://feeds.feedburner.com/ClausHingebjergsFacebookStatusUpdates')"/>
      <xsl:variable name="feedContent2" select="umbraco.library:GetXmlDocumentByUrl('http://feeds.feedburner.com/UploadsByProffartholstebro')"/>
      <xsl:variable name="feedContent3" select="umbraco.library:GetXmlDocumentByUrl('http://feeds.feedburner.com/borsen/wqUp')"/>
      <xsl:variable name="feedContent4" select="umbraco.library:GetXmlDocumentByUrl('http://feeds.feedburner.com/CeramicspeedsFacebookWall')"/>
      <xsl:variable name="feedContent5" select="umbraco.library:GetXmlDocumentByUrl('http://jp.dk/jptv/?service=rssfeed')"/>

      <xsl:call-template name="renderFeed">
        <xsl:with-param name="feedContent" select="$feedContent | $feedContent2 | $feedContent3 | $feedContent4 | $feedContent5"/>
      </xsl:call-template>
    </xsl:template>
        
    <xsl:template name="renderFeed">
      <xsl:param name="feedContent"/>
        <xsl:for-each select="$feedContent//item">
          <xsl:sort select="Exslt.ExsltDatesAndTimes:formatdate(substring (pubDate, 0, 26), 'yyyy-MM-ddTHH:mm:ss')" order="descending" />
             <xsl:if test="position() &lt; 30">
                <div>
                  <style="margin:0px;"><xsl:value-of select="umbraco.library:LongDate(substring (pubDate, 0, 26))"/><br/>
                  <href="{link}">
                    <xsl:if test="author !=''"><xsl:value-of select="author"/><br/>
                    </xsl:if>
                    <xsl:value-of select="title"/>
                  </a>
                  <xsl:if test="contains(link, 'youtube')">
                    <xsl:variable name="myyoutube" select="substring (link, 32, 11)"/>  
                    <iframe width="250" height="150" src="http://www.youtube.com/embed/{$myyoutube}" frameborder="0" allowfullscreen="true">.</iframe>
                  </xsl:if>
                  </p>
                  <xsl:if test="not(contains(link, 'facebook'))">
                    <xsl:choose>
                      <xsl:when test="string(100) != '0'">
                        <style="margin:0px;">
                        <xsl:value-of select="umbraco.library:TruncateString(umbraco.library:StripHtml(description), number(100), '...')" disable-output-escaping="yes"/>
                        </p>
                      </xsl:when>
                      <xsl:otherwise>
                        <xsl:value-of select="description" disable-output-escaping="yes"/>
                      </xsl:otherwise>
                    </xsl:choose>
                  </xsl:if>
                </div>
             </xsl:if>
        </xsl:for-each>
    </xsl:template>

    </xsl:stylesheet>
  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Jul 03, 2011 @ 01:02
    Chriztian Steinmeier
    101

    Hi Claus,

    Oh - when you create the feedUrls in content you can leverage the powerful document() function - if you send it a node-set instead of a URL, it'll treat every node as a URL and fetch 'em all in one go - so here we go:

    <?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"
        xmlns:Exslt.ExsltDatesAndTimes="urn:Exslt.ExsltDatesAndTimes"
        exclude-result-prefixes="umbraco.library"
    >
    
        <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" />
    
        <xsl:param name="currentPage" />
    
        <!-- Grab a reference to the site root (usually on level 1) -->
        <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]" />
    
        <xsl:template match="/">
            <!-- NOTE: You may need to change this XPath, to point to where the feedUrl properties are -->
            <xsl:variable name="feeds" select="document($siteRoot/Feeds/Feed/feedUrl)" />
    
            <!-- Yes - everything is inside $feeds at this point - magic :-) -->
            <xsl:apply-templates select="$feeds//item">
                <!-- Horrendous RFC822 date format is not suitable for sorting, so... -->
                <xsl:sort select="Exslt.ExsltDatesAndTimes:formatdate(substring(pubDate, 0, 26), 'yyyy-MM-ddTHH:mm:ss')" order="descending" />
            </xsl:apply-templates>
    
        </xsl:template>
    
        <!-- Template for an item -->
        <xsl:template match="item">
            <xsl:if test="position() &lt; 30">
                <div>
                    <p style="margin:0px;">
                        <xsl:apply-templates select="pubDate" mode="date" /><br/>
                        <xsl:apply-templates select="title" />
                        <xsl:apply-templates select="link[contains(., 'youtube')]" />
                    </p>
    
                    <xsl:if test="not(contains(link, 'facebook'))">
                        <xsl:choose>
                            <xsl:when test="string(100) != '0'"><!-- Did you mean: string-length(../description &gt; 100) ? -->
                                <p style="margin:0px;">
                                    <xsl:value-of select="umbraco.library:TruncateString(umbraco.library:StripHtml(../description), 100, '...')" disable-output-escaping="yes" />
                                </p>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:value-of select="../description" disable-output-escaping="yes" />
                            </xsl:otherwise>
                        </xsl:choose>
                    </xsl:if>
                </div>
            </xsl:if>
        </xsl:template>
    
        <xsl:template match="title">
            <a href="{../link}">
                <xsl:if test="normalize-space(../author)"><xsl:value-of select="author"/><br/></xsl:if>
                <xsl:value-of select="." />
            </a>
        </xsl:template>
    
        <!-- Format date as LongDate -->
        <xsl:template match="pubDate" mode="date">
            <xsl:value-of select="umbraco.library:LongDate(substring(., 0, 26))" />
        </xsl:template>
    
        <!-- YouTube entry -->
        <xsl:template match="link[contains(., 'youtube')]">
            <xsl:variable name="myyoutube" select="substring(., 32, 11)" />  
            <iframe width="250" height="150" src="http://www.youtube.com/embed/{$myyoutube}" frameborder="0" allowfullscreen="true"><xsl:comment /></iframe>
        </xsl:template>
    
    </xsl:stylesheet>

    I did some other stuff to your code, I know - but I need to spread the "apply-templates virus" to every corner of the world, so... :-) 

    /Chriztian

  • Tom Fulton 2030 posts 4998 karma points c-trib
    Jul 03, 2011 @ 05:36
    Tom Fulton
    0

    Wow, very awesome info Chriztian (as always) - thanks!

  • Claushingebjerg 939 posts 2574 karma points
    Jul 04, 2011 @ 14:51
    Claushingebjerg
    0

    This is so insanely cool. Thanks a bunch. Im 99% there. 1 last thing though (I hope ;) )

    As you can see, i have a <div> around every post. I would like to define eg. a background color on the different feeds. On a feed level... not on a post level.

    Being naive i thought i could just do something like:

    <div>
     <xsl:attribute name="style"
    >
    background-color:#<xsl:value-of select="$siteRoot/Feeds/Feed/bgcolor"/>;
     </xsl:attribute>

    But that colors all feeds the same color... I guess im scoping something wrong... But whaaaaat :)

  • Claushingebjerg 939 posts 2574 karma points
    Jul 04, 2011 @ 16:39
    Claushingebjerg
    0

    Ahh another thing ;). How do i limit the number of posts from each feed, say i only want the 5 newest from each?

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Jul 04, 2011 @ 22:27
    Chriztian Steinmeier
    0

    Hi Claus,

    It's not *that* naïve to think you can do that - but you as I always say: "Remember that you get a *set* back from a select." - so when you say $siteRoot/Feeds/Feed/bgcolor - you're actually getting all the bgcolor elements back, but when you ask for the value-of a set, the processor returns the value from the first in the set.

    So you need to get the bgcolor that sits on the Feed node that has the same feedUrl as the item you're rendering... so how to get that?  If you're lucky, the feeds you're fetching will have an atom:link with a rel="self" attribute - the href atribute on that element should have the URL of the feed, so something like this (remember to add the namespace for the atom prefix):

    <xsl:stylesheet ... xmlns:atom="http://www.w3.org/2005/Atom">
    <xsl:template match="item">
        <xsl:variable name="myURL" select="../atom:link[@rel = 'self']/@href" />
        <xsl:if test="position() &lt; 30">
            <div style="background: #{$siteRoot/Feeds/Feed[feedUrl = $myURL]/bgcolor}">
    ...
    </div>
    </xsl:if>
    </xsl:template>
    (I checked a couple of the feeds you supplied earlier, which has the URL - it sits on an atom10:link element, but through the beauty of namespaces the prefix don't mean a damn thing - pardon my french :-)  

    /Chriztian

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Jul 04, 2011 @ 22:30
    Chriztian Steinmeier
    0

    Regarding the 5 newest - doesn't that conflict a little with your previous top 30 clause? Or did the specs change? :-)

    As you can't sort inside a select, you'll probably have to do some grouping on the feedUrl, and then sort and pick by position... hmmm...

    /Chriztian 

  • Claushingebjerg 939 posts 2574 karma points
    Jul 05, 2011 @ 08:04
    Claushingebjerg
    0

    Well not really... 30 is the numer of items i wnat to show in total.

    What im looking to do is to limit each feed to e.g. 5.

    The reason is, if i have, lets say 6 feeds. Taking the 5 newes from each will guarentee something from all of them gets shown. Otherwise some eager poster can swamp the list with his 30 daily facebook updates :). 

    Hope this makes sense

  • Claushingebjerg 939 posts 2574 karma points
    Jul 07, 2011 @ 16:29
    Claushingebjerg
    0

    Ok, im soooo close now :) im starting to mix the feeds with umbraco nodes and it works, sorta...

    <xsl:template match="/">
        <xsl:variable name="feeds" select="document($siteRoot/Feeds/Feed/feedUrl)" />
             <xsl:apply-templates select="$feeds//item | umbraco.library:GetXmlNodeById(1090)/*">
                     <xsl:sort select="Exslt.ExsltDatesAndTimes:formatdate(substring(pubDate, 0, 26), 'yyyy-MM-ddTHH:mm:ss')" order="descending" />
              </xsl:apply-templates>
     </xsl:template>

    The problem is the sorting. Ive overcome this by making a "pubDate" field on the umbraco nodes...

    What i really would like to do is set the "pubDate" for the umbraco node to "currentdate" at all times, and then stream the time of day from @createDate.

    This would keep the umbraco node at the top of the list, but let feed item mingle in between them during the day...

    So the optimal solution would be to be able to sort on 2 parameters... E.g "pubDate" and "$myDate"

    Any ides how to go about this.?

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Jul 07, 2011 @ 23:20
    Chriztian Steinmeier
    0

    Hi Claus,

    Not entirely sure how you want it sorted (all Umbraco nodes first?) - but you can do something like this, where multiple sort statements are used, but their select attributes are constructed in a way that they're "mutually exclusive":

    <xsl:template match="/">
        <xsl:variable name="today" select="umbraco.library:CurrentDate()" />
        <xsl:variable name="feeds" select="document($siteRoot/Feeds/Feed/feedUrl)" />
        <xsl:apply-templates select="$feeds//item | umbraco.library:GetXmlNodeById(1090)/*">
            <xsl:sort select="concat(self::Feed/feedUrl, ':', $today)" order="descending" />
            <xsl:sort select="concat(self::item/../atom:link[@rel = 'self']/@href, ':', Exslt.ExsltDatesAndTimes:formatdate(substring(pubDate, 0, 26), 'yyyy-MM-ddTHH:mm:ss')" order="descending" />
        </xsl:apply-templates>
    </xsl:template>

    /Chriztian

    (Man this logout thing on Our is getting tedious...)

  • Claushingebjerg 939 posts 2574 karma points
    Jul 08, 2011 @ 08:25
    Claushingebjerg
    0

    I wnat to do a complete mashup, everything sorted in one big list, rss items and umbraco nodes in one big list. I need it mixed :)

Please Sign in or register to post replies

Write your reply to:

Draft