Copied to clipboard

Flag this post as spam?

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


  • Mitra 81 posts 196 karma points
    Nov 05, 2013 @ 08:40
    Mitra
    0

    Splitting a string to array

    Does anyone know how can i split a @nodename like this 091106 to an array like 09,11,06 in xslt file?

    I need to split every two digit in order to get the months like this later:

    April

     

    Thanks,

    Mitra

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Nov 05, 2013 @ 09:01
    Chriztian Steinmeier
    1

    Hi Mitra,

    If the format is very strict, you can use the substring() function to grab the pieces you need:

    <xsl:variable name="month" select="substring(@nodeName, 3, 2)" />
    
    • First argument is the string to search
    • Second argument is the start index (1-based)
    • Third (optional) argument is the number of characters to take

    /Chriztian

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Nov 05, 2013 @ 09:18
    Chriztian Steinmeier
    2

    Another approach would be to use the tokenize() extension to actually perform a split and get a set of results back, but that returns some weird values at times... ideally you can do:

    <xsl:variable name="monthsProxy">
        <month id="01">January</month>
        <month id="02">February</month>
        <month id="03">March</month>
        <!-- etc. -->
    </xsl:variable>
    <xsl:variable name="months" select="msxsl:node-set($monthsProxy)" />
    
    <xsl:for-each select="Exslt.ExsltRegularExpressions:tokenize(@nodeName, '(\d\d)')/match[normalize-space()]">
        <xsl:value-of select="$months[@id = .]" />
    </xsl:for-each>
    

    (The tokenize() method seems to return an empty <match> for every "real" match it finds)

    /Chriztian

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Nov 05, 2013 @ 10:34
    Lee Kelleher
    1

    Hi Mitra,

    Both of Chriztian's solutions will work very well.

    An alternative solution, if you are using the uComponents package, then you could try the ParseExact method (from the Dates XSLT extension:

    <xsl:value-of select="ucomponents.dates:ParseExact(@nodeName, 'ddMMyy', 'MMMM')" />
    

    (I'm assuming that the date format is ddMMyy - please change accordingly)

    The benefit of this approach is that it will use .NET globalization to output the month name in the current culture.

    Cheers,
    - Lee

  • Mitra 81 posts 196 karma points
    Nov 05, 2013 @ 11:52
    Mitra
    0

    Thank you very much for your replies. But i'm again back to my first problem.

    I need to take this array out of the loop and then highlight the months with news.

    if i define the array inside the loop, outside the loop it does not work. and if i define it at the top of my xslt file, the default value does not changes.

    I have tried it with a flag for each months before, and now array but it does not work. my code is like this:

            <xsl:variable name="Array" select="substring(@nodeName, 1, 2)" />
    
            <xsl:variable name='month'>2013-<xsl:value-of select="@nodeName"/>-01</xsl:variable>
    
                           <div class="months">
                               <xsl:choose>   
                                <xsl:when test="contains($Array,'01')"><a href='{umbraco.library:NiceUrl(@id)}' class="news">January</a></xsl:when>
                                <xsl:otherwise>January</xsl:otherwise>
                            </xsl:choose><br/>...
    
  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Nov 05, 2013 @ 12:01
    Chriztian Steinmeier
    0

    Hi Mitra,

    I can see your comments are somehow being caught by the SPAM filter here (the emails go through, so I think I'm able to get what you mean).

    I'll be back with a take on your problem - hang on!

    /Chriztian

  • Mitra 81 posts 196 karma points
    Nov 05, 2013 @ 12:05
    Mitra
    0

    Thanks :(

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Nov 05, 2013 @ 14:48
    Chriztian Steinmeier
    0

    Hi Mitra,

    You should be able to post again now - "SORRY", I'm told :)

    Now let's tackle your problem - could you try posting the structure you have in Content - and the output you're hoping for?

    /Chriztian

  • Mitra 81 posts 196 karma points
    Nov 05, 2013 @ 15:30
    Mitra
    0

    Thanks a lot Chriztian :)

    I'm hoping to see all the months, and hyperlink the once with news.

    All the news system works ok, i am using UNews and DateFolder.

    I have a loop like this:

    <xsl:for-each select="$currentPage/DateFolder">
               
                <xsl:variable name="Array" select="substring(@nodeName, 1, 2)" />
                <xsl:variable name="count" select="count(preceding-sibling::*) + 1" />

    </xsl:for-each>   

    Array for each year i select shows me string with the months something like this 11120410 (means i have got a news in Nov, Dec, April, ... )

    after the look finished i want to check if the month have any news, then hyperlink, otherwise write the month normal, like this:

    January
    February
    March
    April
    May
    June
    July
    August
    September

    October
    November
    December

     


     

    so i say

                                <xsl:choose>   
                                    <xsl:when test="contains($Array,'10')"><a href='{umbraco.library:NiceUrl(@id)}' class="news">October</a></xsl:when>
                                    <xsl:otherwise>October</xsl:otherwise>
                                </xsl:choose><br/>

    but the problem is as soon as i am out of the loop, the Array is not recognised. and if i put this in the loop, then i'll have multiple 12 months (depends how many months have got news)

     

    Sorry for this long message :(

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Nov 05, 2013 @ 23:13
    Chriztian Steinmeier
    100

    Hi Mitra,

    Okay - Since you want all the months, regardless of them having events, you should be making that the main focus and have the outermost "loop" generate the months. Then simply select the DateFolder that matches the month you're currently displaying, and if you get any back, create a link - otherwise print its name... :

    <?xml version="1.0" encoding="utf-8" ?>
    <xsl:stylesheet
        version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:msxsl="urn:schemas-microsoft-com:xslt"
        umbraco.library="urn:umbraco.library"
        exclude-result-prefixes="msxsl umbraco.library"
    >
    
        <xsl:output method="html" indent="yes" omit-xml-declaration="yes" />
    
        <xsl:param name="currentPage" select="/root/Website/YearFolder" />
    
        <!-- Build an XML lookup variable -->
        <xsl:variable name="monthsProxy">
            <month id="01">January</month>
            <month id="02">February</month>
            <month id="03">March</month>
            <month id="04">April</month>
            <month id="05">May</month>
            <month id="06">June</month>
            <month id="07">July</month>
            <month id="08">August</month>
            <month id="09">September</month>
            <month id="10">October</month>
            <month id="11">November</month>
            <month id="12">December</month>
            <!-- etc. -->
        </xsl:variable>
        <xsl:variable name="months" select="msxsl:node-set($monthsProxy)" />
    
        <xsl:template match="/">
            <!-- Go through all the months and check for events -->
            <xsl:for-each select="$months/month">
                <xsl:variable name="monthFolder" select="$currentPage/DateFolder[@nodeName = current()/@id]" />
                <ul>
                    <li>
                        <!-- Create a link to the month folder... -->
                        <xsl:apply-templates select="$monthFolder" mode="link" />
                        <!-- ... or write its name if no events were found -->
                        <xsl:value-of select="self::month[not($monthFolder)]" />
                    </li>
                </ul>
            </xsl:for-each>
        </xsl:template>
    
        <!-- Template for linking the monthname -->
        <xsl:template match="DateFolder" mode="link">
            <a href="{umbraco.library:NiceUrl(@id)}">
                <xsl:apply-templates select="." mode="monthname" />
            </a>
        </xsl:template>
    
        <!-- Template to write the monthname -->
        <xsl:template match="DateFolder" mode="monthname">
            <xsl:value-of select="$months/month[@id = current()/@nodeName]" />
        </xsl:template>
    
    </xsl:stylesheet>
    

    Note: If your DateFolders have single digit names (e.g., "3" instead of "03") just change them in the XML variable.

    Hope I've explained it sufficiently - otherwise, let me know :-)

    /Chriztian

  • Mitra 81 posts 196 karma points
    Nov 06, 2013 @ 14:23
    Mitra
    0

    Many many thanks - The code was great. It worked perfectly ( Although I couldn't really understand how :( )

    I have to learn what you did and how you checked if there is any news...

    Mitra

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

    Hi Mitra,

    It works by the magic of nodesets :-) Whenever you make a selection in XSLT/XPath you're actually getting a nodeset (unless you specifically select a string, a number or a boolean value). Even if a nodeset is empty, it's still a nodeset that you can query.

    So when we select all DateFolder nodes below $currentPage where the @nodeName is the current value in the loop:

    <xsl:variable name="monthFolder" select="$currentPage/DateFolder[@nodeName = current()/@id]" />
    

    Even if no DateFolder matches, the $monthFolder variable is still a nodeset, and we can use it as usual, e.g. use the apply-templates instruction:

    <xsl:apply-templates select="$monthFolder" mode="link" />
    

    This will take every node in the set and find a matching template in the "link" mode, and execute that template with the node as the context. Now, if the set was empty, no templates will have been executed - we didn't even need to do any counting or checking of any kind; neat, right?

    Last piece of the puzzle; this line:

    <xsl:value-of select="self::month[not($monthFolder)]" />
    

    ...translates into "Write the value of the current node (of the for-each loop) if it's a <month> element and the $monthFolder was empty".

    The not() function expects a boolean value, so when we send in a nodeset, the processor will run the variable through the boolean() function first - and that will return false() for an empty nodeset and true() for a nodeset with one or more nodes. So if the $monthsFolder is an empty nodeset, the not() function will return true()...

    Phew, hope that's better :-)

    /Chriztian

  • Mitra 81 posts 196 karma points
    Nov 06, 2013 @ 15:17
    Mitra
    0

    Oh my god - Thank you so much - i have to play with it a little to undretand it better.

    Thanks a lot for your reply. Do you know with this method if i can set the hyperlinks on for the months, even after clicking to the month. What i mean is when i click the month with news, it shows me the relevent news but the hyperlink for all the months will disappear... 

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Nov 06, 2013 @ 15:31
    Chriztian Steinmeier
    1

    You're welcome, no problem :-)

    You can pretty easily make that adjustment - create a variable after the $currentPage param near the top:

    <xsl:param name="currentPage" />
    <xsl:variable name="$yearFolder" select="$currentPage/ancestor-or-self::YearFolder" />
    

    (You may need to tweak this a little - the idea is to go up through the ancestors of the current page to find the "year" folder - use its DocumentType Alias where I've put "YearFolder")

    Then base the $monthFolder variable off of $yearFolder instead:

    <xsl:variable name="monthFolder" select="$yearFolder/DateFolder[@nodeName = current()/@id]" />
    

    Now, any page below (or on) the "Year" node that has this macro, will show the linked months view.

    /Chriztian

  • Mitra 81 posts 196 karma points
    Nov 06, 2013 @ 15:43
    Mitra
    0

    It works :)

    Thanks again.

Please Sign in or register to post replies

Write your reply to:

Draft