Pulling images randomly from an existing datasource
This is an open discussion with 10 replies, filed under Troubleshooting.
Search
It's late and I did not read and understand all of your code, but couldn't you just create a datasource with the sort order
(new and lovely in Symphony 2) random
?
You could use the built-in "random" sort if your data was stored in a Symphony Section. But if your data source is pulling dynamic XML (as the Flickr example may well be), you don't have the ability to query your data prior to including the XML.
Could you have used the random module from EXSLT?
I'm not 100% sure I follow the code either. Can you give an example of what the generate-id() function returns each time? And this random number, is it unique each time the sequence is run?
Nick, you're still up!
generate-id()
will return something like id2115558. The number will be different for every transformation process.
The only guarantee generate-id()
provides (and hence why it's useful in other situations) is that it'll be unique for each element within the context of each process. It's mainly used for generating dynamic in-document (#) anchors, but this is a clever use of the function!
Nice! I'll have to try this out.
I was wanting to pull my LastFM feed and display the top albums I've listened to in the last week, but that feed doesn't have album art info in it. The next best feed with album art would be the top 50 albums in the last 3 months, but then it wouldn't change very often because I'd have to limit my output to the first 10 albums or so. This little trick will let me pick a random sampling from the big list and be different every time, which is way more fun than seeing the few albums I tend to always listen to. :-)
Oops ... I see this only returns 1 random number. Is there a way to randomly grab a few photos instead of just 1?
Oops ... I see this only returns 1 random number. Is there a way to randomly grab a few photos instead of just 1?
There's no reason you can't utilize a predicate and position()
to get additional nodes from the random starting node. It is probably better to go about it this way so you do not get duplicate random nodes.
There's no reason you can't utilize a predicate and position() to get additional nodes from the random starting node. It is probably better to go about it this way so you do not get duplicate random nodes.
I tried that with the random position plus 9 following siblings. The problem I see is if the random position is less than 9 from the last, I won't get the following siblings. I know I could set the total number parameter to 9 less than the actual total, but I don't think that's very random.
Is there a way to add the generate id as an attribute to each, say 'photo' node, and then do a sort on that attribute before outputting? I tried it but I think the xsl:attribute command only works at the end of a transformation and not in the middle of it.
The problem I see is if the random position is less than 9 from the last, I won't get the following siblings. I know I could set the total number parameter to 9 less than the actual total, but I don't think that's very random.
Good point. I'll have to think about this some more.
So what is this new for Symphony 2 sort via random?
Nevermind, I thought it was new code that S2 was utilising, but I realise now it was an option in the DS. I'm happy now.
I have two additional methods of randomly sorting nodes, useful if you can't use the Random sort order directly from a data source.
1. Generate array of random numbers and write into XML
protected function __trigger() { $result = new XMLElement('random'); $numbers = range(1, 50); shuffle($numbers); foreach ($numbers as $number) { if ($number != 0 && $number != "") { $node = new XMLElement('number', $number); $result->appendChild($node); } } return $result; }
Generates the following XML in my page:
<data> <events> <random> <number>17</number> <number>34</number> <number>15</number> <number>24</number> <number>22</number> <number>10</number> <number>38</number> <number>16</number> ...
And using this:
<xsl:for-each select="/data/events/random/number"> <xsl:apply-templates select="/data/other-section/entry[position()=number(current()/text())]" /> </xsl:for-each>
Thw downside is that this is a very inefficient method. My example writes in 50 "number" nodes on the offchance that you might need to sort 50 entries. Not particularly elegant. Therefore a more robust solution:
2. Use EXSLT math:random function to generate a random number
Create an EXSLT nodeset of all entries, but add an attribute to each with a random number. Then sort by this attribute. A full example:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" xmlns:math="http://exslt.org/math" extension-element-prefixes="exsl" > <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:template match="data"> <xsl:variable name="entries"> <xsl:for-each select="/data/my-section/entry"> <entry-container> <xsl:attribute name="random"><xsl:value-of select="floor(math:random() * 10)" /></xsl:attribute> <xsl:copy-of select="." /> </entry-container> </xsl:for-each> </xsl:variable> <xsl:for-each select="exsl:node-set($entries)/entry-container"> <xsl:sort select="@random" order="ascending" data-type="number" /> <!-- apply-templates here --> </xsl:for-each> </xsl:template> </xsl:stylesheet>
Create an account or sign in to comment.
I posted earlier on the Overture21.com site, and added it here, just-in-case it could be of use to anyone. Please let me know your thoughts. If you know a more efficient and better way to code this for Symphony 2 or at all, please let me know. I'm still really new to XSLT game and want to get better.
PROBLEM
I've been trying to figure out a way to randomly display one photo out of a group of images via XSLT every time I refresh my browser.
MY ATTEMPT AT A SOLUTION
After much thought, I came across this solution. It uses the
generate-id()
function and a little magic from themod
operator.NOTE: The generate-id function will return a string like id2115558 when using libXSLT, but for you PHP4 folks that are still using Sablotron (which doesn't apply to the Symphony 2 crowd), when using
generate-id()
you will return a string like i__9022976_0.Here's my example XML (which is based off of Mark Lewis's Flickr Campfire service XML // I manually edited the XML for this example to give proper acknowledgement to the Flickr photographers by adding the
flickrauthor
attribute to each photo node // The photos are buildings from my former University by Flickr users euthman and monochromechicken)...Here's my XSLT (example based off of the libXSLT processor)...