Copied to clipboard

Flag this post as spam?

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


  • praveen 113 posts 164 karma points
    May 03, 2011 @ 02:17
    praveen
    0

    Loop through Page Fields

    Hi There,

    I am new to umbraco and xslt,  thanks for your help in advance.

    I have 5 page fields on the home page as  follows:

    <umbraco:Item field="Story1" runat="server"></umbraco:Item> 
    <umbraco:Item field="Story2" runat="server"></umbraco:Item> 
    <umbraco:Item field="Story3" runat="server"></umbraco:Item> 
    <umbraco:Item field="Story4" runat="server"></umbraco:Item> 
    <umbraco:Item field="Story5" runat="server"></umbraco:Item> 

    I want to write some XSLT so that on every page refresh a  diffrent story text is displayed.

    Many thanks in advance.

    Kind Regards

  • Kim Andersen 1447 posts 2196 karma points MVP
    May 03, 2011 @ 09:43
    Kim Andersen
    0

    Hi praveen

    If you don't have any other fields on your document type that contains 'Story' in the alias, you can loop through the five fields with something like this:

    <xsl:for-each select="$currentPage/*[contains(name(),'Story')]">
    ...
    </xsl:for-each>

    /Kim A

  • praveen 113 posts 164 karma points
    May 04, 2011 @ 00:56
    praveen
    0

    Hi Kim

    Many thanks of your help, how can I print fieldname.value in the loop, please let me know

     <xsl:for-each select="$currentPage/*[contains(name(),'Story')]">
      fieldName.value
                      <umbraco:Item field="StoryOne" runat="server"/>
     </xsl:for-each>

    Kind Regards

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    May 04, 2011 @ 02:10
    Chriztian Steinmeier
    0

    Hi praveen,

    You can print values using the value-of instruction, e.g.:

    <xsl:for-each select="$currentPage/*[starts-with(name(), 'Story')]">
        <p>
            <xsl:value-of select="name()" />: <strong><xsl:value-of select="." /></strong>
        </p>
    </xsl:for-each>

    /Chriztian

  • praveen 113 posts 164 karma points
    May 04, 2011 @ 07:38
    praveen
    0

    Hi Chriztian
    Many thanks for your help.

    <!-- This does not code works-->
    <xsl:for-each select="$currentPage/*[starts-with(name(), 'Story')]">

        <p> 
           <xsl:value-of select="name()" />: <strong><xsl:value-of select="." /></strong>       
        </p>

    </xsl:for-each>


        <!-- This code works-->
    <xsl:for-each select="$currentPage/*[contains(name(),'Story')]">
      
        <umbraco:Item field="StoryOne" runat="server"></umbraco:Item>
        <umb raco:Item field="StoryTwo" runat="server"></umbraco:Item>
        <umb raco:Item field="StoryThree" runat="server"></umbraco:Item>
        <umb raco:Item field="StoryFour" runat="server"></umbraco:Item>
        <umbraco:Item field="StoryFive" runat="server"></umbraco:Item>
    </xsl:for-each>

    I need to diplay a diffrent story on every page refresh

    Kind Regards

  • Pasang Tamang 258 posts 458 karma points
    May 04, 2011 @ 07:56
    Pasang Tamang
    0

    Hi praveen

    Are you asking about like ad rotator? so each time page is refresh different text is displayed. e.g. storyOne for first time and after page refresh story two

    Thanks

  • praveen 113 posts 164 karma points
    May 04, 2011 @ 22:43
    praveen
    0

    Hi Pasang,

    Yes thats right, but I want to flexiability  to dispaly text content only and in some cases images and text content.

    Going back to my original question, how can we read "umbraco:item field" value in the for loop.

    Kind Regards

  • Lennart Stoop 304 posts 842 karma points
    May 04, 2011 @ 23:12
    Lennart Stoop
    0

    Hi praveen,

    Did you perhaps copy/paste the XSLT code directly into the template? For the XSLT to work you will have to create a macro first:

    1) In the Developer section under "XSLT files" create a new XSLT file

    2) Copy/Paste Chriztian's XSLT code into the XSLT file (right under xsl:template)

    3) Go back to the template in the Settings section and insert the macro (4th icon from the left)

  • Dirk Seefeld 126 posts 665 karma points
    May 05, 2011 @ 00:49
    Dirk Seefeld
    0

    Hi praveen,

    I think the problem is the upper S in 'Story'. When you create a new property name like Story1, umbraco automatically creates an alias name with lowercase s as first letter. Try this for the loop:


    <xsl:for-each select="$currentPage/*[starts-with(name(), 'story')]">

        <p> 
           <xsl:value-of select="name()" />: <strong><xsl:value-of select="." /></strong>       
        </p>

    </xsl:for-each>

    Your initial question was how to select a random property value.
    May be this helps

    <?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:msxsl="urn:schemas-microsoft-com:xslt"
        xmlns:randomTools="http://www.umbraco.org/randomTools"
      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:tagsLib="urn:tagsLib" xmlns:BlogLibrary="urn:BlogLibrary"
      exclude-result-prefixes="msxml
    msxsl randomTools umbraco.library Exslt.ExsltCommon
    Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions
    Exslt.ExsltStrings Exslt.ExsltSets tagsLib BlogLibrary "
    >


      <msxsl:script language="c#" implements-prefix="randomTools">
        <msxsl:assembly href="../bin/umbraco.dll"/>
        <![CDATA[
            /// <summary>
            /// Gets a random integer that falls between the specified limits
            /// </summary>
            /// <param name="lowerLimit">An integer that defines the lower-boundary of the range</param>
            /// <param name="upperLimit">An integer that defines the upper-boundary of the range</param>
            /// <returns>A random integer within the specified range</returns>
            public static int GetRandom(int lowerLimit,int upperLimit) {
                Random r = umbraco.library.GetRandom();
                int returnedNumber = 0;
                lock (r)
                {
                    returnedNumber = r.Next(lowerLimit, upperLimit);
                }
                return returnedNumber;
            }
        ]]>
      </msxsl:script>
          
      <xsl:output method="xml" omit-xml-declaration="yes" />

      <xsl:param name="currentPage"/>
            

      <xsl:template match="/">
        <xsl:variable name="r" select="string(randomTools:GetRandom(1,4))" />
        <xsl:variable name="x" select="position()"/>

        <xsl:value-of select="$currentPage/*[name()= concat('story',$r)]" />
      </xsl:template>
         
    </xsl:stylesheet>

     

     

    /Dirk

  • Sean Holmesby 61 posts 82 karma points
    May 05, 2011 @ 02:24
    Sean Holmesby
    0

    Hi praveen,

    Dirk's solution looks the best for what you are trying to do, however you may want to change the fields to 'Story1', 'Story2' etc.... instead of 'StoryOne', 'StoryTwo' etc...

    That could be your problem... because I noticed you had those field names in your initial post, but not in your follow up posts.

     

    If you use Dirk's method, make sure that the alias' for each of your fields are exactly (case sensitive) 'story1', 'story2' etc....

     

    - Sean

  • praveen 113 posts 164 karma points
    May 05, 2011 @ 02:27
    praveen
    0

    Hi Dirk

    I tried lower/upercase 'story' and it dose not help.

    As advised I created an XSLT file in the developer section and inserted the Macro in the template
    and it dose not work.

    <!--CODE FROM THE XSLT FILE -- >                                                          

     <xsl:template match="/">   
    <!-- start writing XSLT -->
    <xsl:for-each select="$currentPage/*[contains(name(),'Story')]">
     <xsl:value-of select="data [@alias = 'StoryOne']"/>
    </xsl:for-each>

    <xsl:for-each select="$currentPage/*[starts-with(name(), 'Story')]">
    <p>               
    <xsl:value-of select="name()" />: <strong><xsl:value-of select="." /></strong>       
    </p>
    </xsl:for-each>
    </xsl:template>

    <!--MACRO FROM THE TEMPLATE-- >   
    <umbraco:Macro Alias="XSLTFeatureNews" runat="server"></umbraco:Macro>

    However when I directly insert the page field in the template it WORKS.
    <umbraco:Item field="Story1" runat="server"></umbraco:Item>

    Many thanks for your help and thanks for your patience.

    Best Regards
                                                          
       

  • praveen 113 posts 164 karma points
    May 05, 2011 @ 02:51
    praveen
    0

    Hi there

    I have recreated the page fields and used Dirk XSLT  macro, and it dose not work. please help

  • Sean Holmesby 61 posts 82 karma points
    May 05, 2011 @ 05:20
    Sean Holmesby
    0

    Hi praveen,

    Is your issue that the macro isn't being run at all? Check that the alias of the macro (XSLTFeatureNews) is the same as is listed for that macro in the developer section. Check for case sensitivity as well.

    Maybe just put some text in the start of your XSLT to see that it's being hit. So....

    <xsl:template match="/">

        TEST

    <!-- start writing XSLT -->
    <xsl:for-each select="$currentPage/*[contains(name(),'Story')]">
     <xsl:value-of select="data [@alias = 'StoryOne']"/>
    </xsl:for-each>

    <xsl:for-each select="$currentPage/*[starts-with(name(), 'Story')]"> 
    <p>                
    <xsl:value-of select="name()" />: <strong><xsl:value-of select="." /></strong>        
    </p>
    </xsl:for-each>
    </xsl:template>

    Then you should at least see the word 'TEST' on the page.

     - Sean

  • Dirk Seefeld 126 posts 665 karma points
    May 05, 2011 @ 08:30
    Dirk Seefeld
    0

    Hi praveen,

    which version of umbraco are you using? My first xslt script was for version 4.7 (should work since 4.5). But if your version is below 4.5 you may try this:

    <?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:msxsl="urn:schemas-microsoft-com:xslt"
    xmlns:randomTools="http://www.umbraco.org/randomTools"
    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:tagsLib="urn:tagsLib" xmlns:BlogLibrary="urn:BlogLibrary"
    exclude-result-prefixes="msxml
    msxsl randomTools umbraco.library Exslt.ExsltCommon
    Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions
    Exslt.ExsltStrings Exslt.ExsltSets tagsLib BlogLibrary ">


    <msxsl:script language="c#" implements-prefix="randomTools">
    <msxsl:assembly href="../bin/umbraco.dll"/>
    <![CDATA[
    /// <summary>
    /// Gets a random integer that falls between the specified limits
    /// </summary>
    /// <param name="lowerLimit">An integer that defines the lower-boundary of the range</param>
    /// <param name="upperLimit">An integer that defines the upper-boundary of the range</param>
    /// <returns>A random integer within the specified range</returns>
    public static int GetRandom(int lowerLimit,int upperLimit) {
    Random r = umbraco.library.GetRandom();
    int returnedNumber = 0;
    lock (r)
    {
    returnedNumber = r.Next(lowerLimit, upperLimit+1);
    }
    return returnedNumber;
    }
    ]]>
    </msxsl:script>

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

    <xsl:param name="currentPage"/>


    <xsl:template match="/">
    <xsl:variable name="r" select="concat('story',string(randomTools:GetRandom(1,5)))" />
    <xsl:value-of select="$currentPage/ancestor-or-self::node/data [@alias = $r]" />

    </xsl:template>

    </xsl:stylesheet>

    Dirk

  • praveen 113 posts 164 karma points
    May 06, 2011 @ 00:02
    praveen
    0

    Hi Sean,

    Thanks for the reply  TEST 0 and TEST 3 does print
    TEST 1 and TEST2 DOES NOT PRINT

    Dirk, I am using umbraco 4.0

    TEST 0

    <!-- start writing XSLT -->
    <xsl:for-each select="$currentPage/*[starts-with(name(), 'story')]">
    TEST 1

            <p>               
               <xsl:value-of select="name()" />: <strong><xsl:value-of select="." /></strong>       
            </p>
    </xsl:for-each>

    <xsl:for-each select="$currentPage/*[contains(name(),'story')]">
    TEST 2

            <p>               
               <xsl:value-of select="name()" />: <strong><xsl:value-of select="." /></strong>       
            </p>
    </xsl:for-each>
    TEST 3

    Thanks for y our help

    Kind Regards

  • Sean Holmesby 61 posts 82 karma points
    May 06, 2011 @ 03:15
    Sean Holmesby
    0

    Hmmm, the code looks ok (I think). Dirk, can you see any issues with it? The XSLT is obviously working as the macro code...

    I think I had a similar issue the other day with the field names, but only after I had changed the field names.

    If you have changed the field names in the Document Type, you should go and save and publish the document(s) that use that Document Type again. This way they will have the new field names in the xml they produce.

    A good thing you may want to do to check the data:-

    outside of your <xsl:for-each loop, just output the data of everything in the currentPage.

    <xsl:value-of select="$currentPage" />

  • praveen 113 posts 164 karma points
    May 06, 2011 @ 07:39
    praveen
    0

    Hi Dirk, Many thanks for your help, I did saved and published the page, but it does not help

     This code works displays all the data.

    <xsl:value-of select="$currentPage" />

  • Sean Holmesby 61 posts 82 karma points
    May 06, 2011 @ 08:27
    Sean Holmesby
    0

    Hi praveen,

    Can you post what it displays?

     - Sean

  • Dirk Seefeld 126 posts 665 karma points
    May 06, 2011 @ 09:38
    Dirk Seefeld
    1

    Hi praveen, Hi Sean,

    well I think praveen has already mentioned the issue ;-) - using version 4.0!

    4.5 chanded the xslt parser schema there are a wiki about the changes: http://our.umbraco.org/wiki/reference/xslt/45-xml-schema

    Sean Test snippet should look like this:

    TEST 0

    <!-- start writing XSLT -->

    <xsl:for-each select="$currentPage/ancestor-or-self::node/data [starts-with(@alias,'story')]">
    TEST 1
    <p>
    story <xsl:value-of select="position()"/>: <strong><xsl:value-of select="." /></strong>
    </p>
    </xsl:for-each>

    <xsl:for-each select="$currentPage/ancestor-or-self::node/data [contains(@alias,'story')]">
    TEST 2

    <p>
    story <xsl:value-of select="position()"/>: <strong><xsl:value-of select="." /></strong>
    </p>
    </xsl:for-each>
    TEST 3

    I dont think you have access to the property alias, but at least I am not an xslt expert. And for the given problem I can not see a problem with this - you should not need to reed the name. position might be satisfying.

    @praveen: Have you tried my second random script for version below 4.5 e. g. 4.0?

    Dirk

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    May 06, 2011 @ 11:38
    Lee Kelleher
    1

    Hi praveen,

    Here's an alternative take on the problem...

    I'd highly recommend that you don't use the inline <msxml:script> code blocks - they are bad, bad, bad news! (No offense to Dirk!)

    My suggestion is to make use of the ExsltDatesAndTimes extensions, like so...

    <?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="/">
    
            <!--
                Uses the 'secondinminute' to return a value between 0 and 59,
                then take the modulus of the seconds (by the total nodes) and increment by 1 (as e.g. 30 % 5 == 0)
            -->
            <xsl:variable name="index" select="(Exslt.ExsltDatesAndTimes:secondinminute() mod 5) + 1" />
    
            <!-- Use concat to construct the alias name -->
            <xsl:value-of select="$currentPage/data[@alias = concat('story', $index)]"/>
    
        </xsl:template>
    
    </xsl:stylesheet>

    The idea here is that you make a call "Exslt.ExsltDatesAndTimes:secondinminute()", this will return a value between 0 and 59 ... then you take the modulus of 5 from that value (plus 1 ... as you don't want a value of zero!)

    Once you've got that index number, you can then use it in a <xsl:value-of> to return the "random" story.

    If you wanted to slow down the random/rotation - you could switch the "secondinminute" to something else like "hourinday" or "dayinweek"?

    Good luck!

    Cheers, Lee.

  • Dirk Seefeld 126 posts 665 karma points
    May 06, 2011 @ 17:51
    Dirk Seefeld
    1

    Hi Lee,

    goog idea to use the timer. I was also not happy about the inline code but found that hack somewhere in this forum.

    I would give High Five but my karma is still to low ;-)

    Dirk

  • praveen 113 posts 164 karma points
    May 07, 2011 @ 03:11
    praveen
    0

    High five to Dirk, LEE, LEE,LEE :),Sean, Kim, Chriztian, Pasang, Lennart
    Many many many thanks to all you guys,

    Lees, example worked !!!

    Guys you have every right to shoot me down, I should have told you Umbraco Version that I am using in the first place :(
    Many thanks for your help.

    Best Regards

  • Sean Holmesby 61 posts 82 karma points
    May 07, 2011 @ 12:27
    Sean Holmesby
    0

    Haha.... nice one Praveen... that one slipped by me. Good work to the guys for their solutions.

    Glad you got it working.

     - Sean

Please Sign in or register to post replies

Write your reply to:

Draft