Copied to clipboard

Flag this post as spam?

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


  • Stefan 117 posts 215 karma points
    Aug 06, 2013 @ 20:51
    Stefan
    0

    Include xslt file (reuse code)

    I have some XSLT code snippets that I reuse in many different XSLT stylesheets. A big headache is that when I use the to include the code in another file, then I have to touch this file whenever changes are made to my.xslt. I've read about something called XSLTouch, but that seems as a very inappropriate solution, since I would like the files to be touched whenever my.xslt is changed.

    Does anyone know about a proper solution to this, or maybe other workarounds as other ways of reusing XSLT code?

    Thanks!

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Aug 06, 2013 @ 21:53
    Chriztian Steinmeier
    100

    Hi Stefan,

    Have you actually tried XSLTouch? It does exactly that - it touches your main XSLT file whenever any included XSLT file is changed, so it gets recompiled. I've used it for years now, since I use lots of include files... :-)

  • Stefan 117 posts 215 karma points
    Aug 07, 2013 @ 11:23
    Stefan
    0

    Doh! Why on earth did I not think of looking in the repository :P

    So, thank you for your suggestions - and mentioning the XSLT helper files - I'm diving into the world of easy-pagination straight away :)

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Aug 07, 2013 @ 11:30
    Chriztian Steinmeier
    0

    Awesome - let me know if it's working for you or not!

    /Chriztian

  • Stefan 117 posts 215 karma points
    Aug 07, 2013 @ 14:41
    Stefan
    0

    It is working very well! I'm really happy about how easy pagination is to implement using the helper XSLT files! One thing though; How can I use templates to sort my content according to create-date as I would with

    I would also like to add more functionality to my products listing besides pagination. I have a

    element on the page which contains some UI elements that are going to be used to filter the products according to various data on the product document-type (for example min/max price and the actual documenttype for the product (since a product can be one of three types).

    Any help is greatly appreciated :) Thanks!

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Aug 07, 2013 @ 15:05
    Chriztian Steinmeier
    0

    Hi Stefan,

    Glad to hear you like it - really!

    There is a branch on GitHub with a version of the PaginationHelper that lets you do some of the most common sorting scenarios - check that out for the first one.

    For the other one - make sure your page works without pagination, using querystring parameters, e.g.: ?minprice=100&maxprice=1000 etc.

    These variables will survive through the pagination process, and any filtering you want to do, you can access these in the XSLT as $options[@key = 'minprice'] for convenience.

    /Chriztian

    (Update: Added link to the specific file)

    (Update 2: Used that correct link :-)

  • Stefan 117 posts 215 karma points
    Aug 08, 2013 @ 12:57
    Stefan
    0

    Thank you very much for your help. For some reason I was getting DTD errors for the branched version of PaginationHelper. I didn't want to spend too much time dealing with it, so I removed the entities and made changes where due in the document, which made it run as supposed.

    But I'm sure its me that missed out on something :P

    And thanks for the tip regarding the querystring parameters!

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Aug 08, 2013 @ 13:54
    Chriztian Steinmeier
    0

    Hi Stefan,

    My bad - I didn't provide a decent link (which I said I had). I've fixed it now but here it is again.

    It's because you should grab the files from the dist/ directory on GitHub — they've been cleaned for entities etc. so you don't have to have any of that...

    I really should get that package out the door soon...

    /Chriztian

  • Stefan 117 posts 215 karma points
    Aug 09, 2013 @ 15:46
    Stefan
    0

    Haha, that would surely be a nice thing to do, even though it is working fine as-is.

    Now, I also decided to use the MediaHelper templates, but this is giving me some trouble.
    Is it possible to iterate through DAMP images with a for-each and from that call the helper methods to insert the DAMP images (one at a time for each iteration)?

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Aug 09, 2013 @ 16:04
    Chriztian Steinmeier
    0

    It's actually as simple as this:

    <xsl:apply-templates select="$currentPage/images" mode="media" />
    

    This will render each of the images picked using the default Image template in the MediaHelper. It auto-detects DAMP but only works when you've configured DAMP to store the full media XML.

    Let me know if that's not what you want

    /Chriztian

  • Stefan 117 posts 215 karma points
    Aug 09, 2013 @ 16:42
    Stefan
    0

    This is what I have been using. The problem is that it renders every image stored with the DAMP picker.
    What I want is to render each image individually from a for-each iteration.

    This is how it looks without using the helpers:

    <xsl:for-each select="$currentPage/dampSlider/DAMP/mediaItem/ImageFrontpageSlider">
      <a href="#">
        <xsl:attribute name="data-slide-index">
          <xsl:value-of select="position() - 1" />
        </xsl:attribute>
        <img>
          <xsl:attribute name="src">
            <xsl:value-of select="crops/crops/crop[@name='SliderSmall']/@url" />
          </xsl:attribute>
          <xsl:attribute name="alt">
            <xsl:value-of select="@nodeName" />
          </xsl:attribute>
        </img>
        <h5>...</h5>
      </a>
    </xsl:for-each>

    It would be nice if I could replace the <img>...</img> with a call to the helper template.

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Aug 09, 2013 @ 16:57
    Chriztian Steinmeier
    0

    I hear you loud and clear :-)

    This is how you'd do that - but it requires you to add your crop definitions to the config/CroppingSettings.config as described in the README for _MediaHelper.xslt:

    UPDATE: You only need to add the .config file if you need the correct width & height attributes. Just read the README again myself :-)

    <xsl:for-each select="$currentPage/dampSlider/DAMP/mediaItem/ImageFrontpageSlider">
        <a href="#" data-slide-index="{position() - 1}">
            <xsl:call-template name="GenericImage">
                <xsl:with-param name="crop" select="'SliderSmall'" />
            </xsl:call-template>
            <h5>...</h5>
        </a>
    </xsl:for-each>
    

    /Chriztian

  • Stefan 117 posts 215 karma points
    Aug 24, 2013 @ 19:03
    Stefan
    0

    Sorry to bother you again, but I thought that this would be the proper place to ask a related question (if anyone is even "listening"...).

    I've been very happy with your _PaginationHelper.xslt templates, and have included pagination for many pages. But, now the time has come to filter the contents based on a form from where you can select some criteria, providing the page with a query string when submitted.

    This is working perfectly, but I really can't get my head around how I can use the query string most efficiently together with the pagination helper templates.

    At the moment (when not doing anything with the query string), I'm feeding the pagination helper with the following selection:

    <xsl:variable name="paginationSelection" select="$currentPage/descendant::*[@isDoc and @level = 5]" />
    

    This is what I could get from the query string:

    ?year=undefined&month=all&news=on&events=on&fairs=on
    

    Year and month are values provided by a <select> and should ideally redirect to other pages (since I'm using Autofolders - or maybe match the @createDate of the nodes.

    News, events and fairs are checkboxes that specifies the document types to show.

    I have been playing around with xsl:variables, specifying the select using a choose statement. But that did not work as expected, so if you can provide me with a push in the right direction, it would be greatly appreciated :)

    Thanks!

  • Stefan 117 posts 215 karma points
    Aug 24, 2013 @ 19:07
    Stefan
    0

    Argh, double post...

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Aug 25, 2013 @ 21:39
    Chriztian Steinmeier
    0

    Hi Stefan,

    So here's the trick to doing those kinds of operations, though I'd probably recommend you team up with a good .NET developer, who can write a couple of custom extensions for advanced filtering methods. There's a limit to how much of this should be done in the "view", regardless of language (i.e. whether using Razor, XSLT or something else).

    If you're using the Pagination Helper you've got the $options variable, for grabbing the values of the QueryString, so you create a boolean variable for each of the keys and use those to effectively switch a set on or off, depending on the value.

    This is the relevant code - hope I explained it OK (please note that you need to change the document type aliases NewsItem and Event to the actual names you're using):

    <!-- Grab all the possible nodes -->
    <xsl:variable name="nodes" select="$currentPage//*[@isDoc and @level = 5]" />
    
    <!-- Get a boolean for every QueryString param -->
    <xsl:variable name="newsOn" select="boolean($options[@key = 'news'] = 'on')" />
    <xsl:variable name="eventsOn" select="boolean($options[@key = 'events'] = 'on')" />
    
    <!-- Select nodes (or an empty set, if not 'on')  -->
    <xsl:variable name="newsNodes" select="$nodes[self::NewsItem and $newsOn]" />
    <xsl:variable name="eventNodes" select="$nodes[self::Event and $eventsOn]" />
    
    <!-- Join the two sets for rendering -->
    <xsl:variable name="paginationSelection" select="$newsNodes | $eventNodes" />
    
    <xsl:template match="/">
        <!-- Process the selected nodes using their specific templates and paginate the results -->
        <xsl:call-template name="PaginateSelection">
            <xsl:with-param name="selection" select="$paginationSelection" />
        </xsl:call-template>
    </xsl:template>
    
    <xsl:template match="NewsItem">
        <p><xsl:value-of select="@nodeName" /> (News)</p>
    </xsl:template>
    
    <xsl:template match="Event">
        <p><xsl:value-of select="@nodeName" /> (Event)</p>
    </xsl:template>
    

    /Chriztian

  • Stefan 117 posts 215 karma points
    Aug 26, 2013 @ 14:06
    Stefan
    0

    Thanks a bunch! But actually, I've beaten you to the finishline - I did come up with a solution (this night, phew), but I can't decide whether it is an efficient solution or not. The plan is also to be able to filter by createdate (either through the @createDate variable or by some URL redirect since I'm using Autofolders), but thats another headache.

    Here is what I did come up with:

    <xsl:variable name="filterYear" select="umbraco.library:RequestQueryString('year')" />
    <xsl:variable name="filterMonth" select="umbraco.library:RequestQueryString('month')" />
    <xsl:variable name="filterNews" select="umbraco.library:RequestQueryString('news')" />
    <xsl:variable name="filterEvent" select="umbraco.library:RequestQueryString('events')" />
    <xsl:variable name="filterFair" select="umbraco.library:RequestQueryString('fairs')" />
    
    <xsl:variable name="filterSelection">
        <xsl:choose>
            <xsl:when test="normalize-space($filterNews) and normalize-space($filterEvent) and not(normalize-space($filterFair))">
                <xsl:value-of select="'[(self::NewsItem | self::NewsEvent) and @isDoc and @level = 5]'" />
            </xsl:when>
            <xsl:when test="normalize-space($filterNews) and normalize-space($filterFair) and not(normalize-space($filterEvent))">
                <xsl:value-of select="'[(self::NewsItem | self::NewsFair) and @isDoc and @level = 5]'" />
            </xsl:when>
            <xsl:when test="normalize-space($filterEvent) and normalize-space($filterFair) and not(normalize-space($filterNews))">
                <xsl:value-of select="'[(self::NewsEvent | self::NewsFair) and @isDoc and @level = 5]'" />
            </xsl:when>
            <xsl:when test="normalize-space($filterNews) and not(normalize-space(concat($filterEvent, $filterFair)))">
                <xsl:value-of select="'[self::NewsItem and @isDoc and @level = 5]'" />
            </xsl:when>
            <xsl:when test="normalize-space($filterEvent) and not(normalize-space(concat($filterNews, $filterFair)))">
                <xsl:value-of select="'[self::NewsEvent and @isDoc and @level = 5]'" />
            </xsl:when>
            <xsl:when test="normalize-space($filterFair) and not(normalize-space(concat($filterNews, $filterEvent)))">
                <xsl:value-of select="'[self::NewsFair and @isDoc and @level = 5]'" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="'[@isDoc and @level = 5]'" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    
    <xsl:variable name="paginationSelection"
    select="ucomponents.xml:FilterNodes($currentPage, concat('/descendant::*', $filterSelection))" />

    I find it a little messy, but as mentioned, my biggest concern is efficiency. 

    Doing it this way I can also see a quite easy solution to the createDate problem; I could add some conditions to the @createDate attribute of the node to limit the filtering.

    Thanks again, I really find your comments helpfull! Also, working with the pagination helper has kickstarted my use of templates, yay!

Please Sign in or register to post replies

Write your reply to:

Draft