Copied to clipboard

Flag this post as spam?

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


  • Chad Schulz 13 posts 46 karma points
    Dec 10, 2010 @ 21:11
    Chad Schulz
    0

    Xslt Recursion Parent Traversal

    I wrote some Xslt to display a header image for a specific page. If the page does not have one uploaded it searches its parent (to keep a section the same). It continues up the content tree until if find on with a banner image, and it uses it. The root page has the default banner image used throughout the site for in the rare case a page traverses all the way to the root.

    I was excited about it and wanted to share, but also looking for feedback. Is there a better/different way to do it? Can this be stramlined?

    <xsl:param name ="currentPage" />

      <xsl:param name ="alternateText" select="$currentPage/pageTitle" />

     

      <xsl:template match="/">

     

        <!-- start writing XSLT -->

        <div id="interior-banner">

          <img>

     

            <xsl:attribute name="src">

              <xsl:call-template name="bannerImage">

                <xsl:with-param name="currentID" select="$currentPage/@id"/>

              </xsl:call-template>

            </xsl:attribute>

     

            <xsl:if test="$alternateText != ''">

              <xsl:attribute name="alt">

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

              </xsl:attribute>

            </xsl:if>

     

            <xsl:if test="$alternateText != ''">

              <xsl:attribute name="alt">

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

              </xsl:attribute>

            </xsl:if>

     

            <xsl:attribute name="height">240</xsl:attribute>

            <xsl:attribute name="width">980</xsl:attribute>

          </img>

        </div>

     

      </xsl:template>

     

      <xsl:template name="bannerImage">

        <xsl:param name="currentID" />

     

          <xsl:if test="umbraco.library:GetXmlNodeById(string($currentID))/interiorBannerImage = ''">

            <xsl:if test="string($currentID) != ''">

              <xsl:call-template name="bannerImage">

                <xsl:with-param name="currentID" select="umbraco.library:GetXmlNodeById($currentID)/../@id" />

              </xsl:call-template>

            </xsl:if>

          </xsl:if>

     

          <xsl:variable name="mediaNode" select="umbraco.library:GetXmlNodeById(string($currentID))/interiorBannerImage" />

          <xsl:if test="$mediaNode != ''"><xsl:value-of select="umbraco.library:GetMedia($mediaNode, 1)/umbracoFile" /></xsl:if>

     

      </xsl:template>

  • Chad Schulz 13 posts 46 karma points
    Dec 10, 2010 @ 21:21
    Chad Schulz
    0

    I am also unable to wrap the code with 'code' style. Nor can I delete this post to update it. If you have the ability, please fix. :(

  • Chriztian Steinmeier 2800 posts 8791 karma points MVP 8x admin c-trib
    Dec 11, 2010 @ 00:48
    Chriztian Steinmeier
    0

    Hi Chad,

    There's a couple of things you can do to streamline this - here's a shorter version:

       <xsl:template match="/">
            <div id="interior-banner">
                <img width="980" height="240" alt="{$currentPage/@nodeName}">
                    <xsl:attribute name="src">
                        <xsl:apply-templates select="$currentPage/ancestor-or-self::*[normalize-space(interiorBannerImage)][1]/interiorBannerImage" />
                    </xsl:attribute>
                    <xsl:if test="normalize-space($alternateText)">
                        <xsl:attribute name="alt">
                            <xsl:value-of select="$alternateText" />
                        </xsl:attribute>
                    </xsl:if>
                </img>
            </div>
        </xsl:template>
    
        <xsl:template match="interiorBannerImage">
            <xsl:variable name="mediaNode" select="umbraco.library:GetMedia(., true())" />
            <xsl:if test="not($mediaNode[error])">
                <xsl:value-of select="umbracoFile" />
            </xsl:if>
        </xsl:template>
    
    Notice the XPath for the src attribute - it does the trick of taking the interiorBannerImage property from either $currentPage, $currentPage's parent or the parent's parent etc. (the key here is the ancestor-or-self:: axis - check it out here).
    I've also moved the width, height and alt attributes into the tag as literal attributes (the alt attribute will be overwritten if $alternateText has a value).

    /Chriztian

  • Neil Tootell 73 posts 118 karma points
    Mar 10, 2011 @ 16:42
    Neil Tootell
    0

    Hi Chad - this is really great thanks - I pulled the logic and used perfectly on my own site.

    I use a function to call images and it makes your function very tidy

    Here's the function I use from my XSLT includes folder...

    <xsl:template name="Utils.DisplayImage">
            <xsl:param name="imageId"/>
            <xsl:param name="imagePathOnly"/>
            <xsl:param name="imageWidth"/>
            <xsl:param name="imageAltOverride"></xsl:param>
            <xsl:param name="imageClass"></xsl:param>
            <xsl:if test="$imageId != ''">
                <xsl:variable name="mediaXml" select="umbraco.library:GetMedia($imageId, 0)"/>
                <xsl:variable name="umbracoFile" select="$mediaXml/umbracoFile"/>
                <xsl:variable name="umbracoWidth" select="$mediaXml/umbracoWidth"/>
                <xsl:variable name="umbracoAlt">
                    <xsl:choose>
                        <xsl:when test="$imageAltOverride != ''">
                            <xsl:value-of select="$imageAltOverride" />
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:value-of select="$mediaXml/umbracoAlt" />
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:variable>
                <xsl:choose>
                    <xsl:when test="$imagePathOnly = '1'">
                        <xsl:value-of select="$umbracoFile"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <img>
                            <!-- Use ImageGen to resize on the fly if needed -->
                            <xsl:choose>
                                <xsl:when test="$imageWidth != '' and number($umbracoWidth) &gt; $imageWidth">
                                    <xsl:attribute name="src">
                                        <xsl:value-of select="concat($imageGeneratorPath, '?image=', $umbracoFile, '&amp;width=', $imageWidth)"/>
                                    </xsl:attribute>
                                </xsl:when>
                                <xsl:otherwise>
                                    <xsl:attribute name="src">
                                        <xsl:value-of select="$umbracoFile"/>
                                    </xsl:attribute>
                                </xsl:otherwise>
                            </xsl:choose>
                            <!-- Add class if needed -->
                            <xsl:if test="string($imageClass) != ''">
                                <xsl:attribute name="class">
                                    <xsl:value-of select="$imageClass"/>
                                </xsl:attribute>
                            </xsl:if>
                            <!-- Add alt text -->
                            <xsl:attribute name="alt">
                                <xsl:value-of select="$umbracoAlt"/>
                            </xsl:attribute>
                        </img>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:if>
        </xsl:template>

    If you don't use imageGen you'll need to strip that bit out, but a basic 4.6+ call to it goes like this...

    <xsl:call-template name="Utils.DisplayImage">
    <xsl:with-param name="imageId" select="$pageImage"/>
    </xsl:call-template>

     

    Many thanks for you recursiveness :)

    Neil

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies