Copied to clipboard

Flag this post as spam?

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


  • Warren Buckley 2106 posts 4836 karma points MVP 7x admin c-trib
    Nov 19, 2009 @ 13:33
    Warren Buckley
    1

    xsl include & reusing include as seperate macro

    Hello all,
    OK I am not 100% sure if this can be done, but it would be great if could be.

    Currently I have an XSLT that refernces an included XSLT file that it is re-used in several places. In this case I have a share facebook & print link in the included XSLT.

    What I would like to do is to have a Macro setup to point directly to the included XSLT file. So I can call it from masterpages directly.

    Here is the current setup for the template that references the include and it works just fine when used as an include

    <!-- XSLT Template Includes -->
    <xsl:include href="../Common/ToolboxLinks.xslt"/>

    <xsl:param name="currentPage"/>

    <xsl:template match="/">
      <!-- Some other stuff & logic -->

      <!-- Article tools -->
      <xsl:call-template name="toolboxLinks" />
    </xsl:template>

    This is the full XSLT for the included file:

    <?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.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"
        exclude-result-prefixes="msxml umbraco.library Exslt.ExsltCommon Exslt.ExsltDatesAndTimes Exslt.ExsltMath Exslt.ExsltRegularExpressions Exslt.ExsltStrings Exslt.ExsltSets ">

      <xsl:output method="html" omit-xml-declaration="yes"/>
     
      <xsl:variable name="prefix">http://</xsl:variable>;
      <xsl:variable name="serverName" select="umbraco.library:RequestServerVariables('SERVER_NAME')"/>
      <xsl:variable name="pageURL" select="concat($prefix,$serverName,umbraco.library:NiceUrl($currentPage/@id))"/>

     
      <xsl:template match="/">
        <xsl:call-template name="toolboxLinks"/>
      </xsl:template>
     
      <xsl:template name="toolboxLinks">   
        <div id="article-tools">
          <a href="http://www.facebook.com/sharer.php?u={$pageURL}" class="facebook-link">Del Pa Facebook</a>
          <a href="{$currentPage/@urlName}/print.aspx" class="print-link">Skriv ut</a>
        </div>   
      </xsl:template>

    </xsl:stylesheet>

    But on the page where I call it with just the macro and not as an include it doesn't work.

    The error I get is as follows:

    Error loading XSLT Common/ToolboxLinks.xsltThe variable or parameter 'currentPage' is either not defined or it is out of scope.
    at System.Xml.Xsl.XslCompiledTransform.LoadInternal(Object stylesheet, XsltSettings settings, XmlResolver stylesheetResolver)
    at System.Xml.Xsl.XslCompiledTransform.Load(XmlReader stylesheet, XsltSettings settings, XmlResolver stylesheetResolver)
    at umbraco.macro.CreateXsltTransform(XmlTextReader xslReader, Boolean debugMode)
    at umbraco.macro.getXslt(String XsltFile)
    at umbraco.macro.loadMacroXSLT(macro macro, Hashtable attributes, Hashtable pageElements)


    Any ideas people?
    Has anyone even attempted something like this before?

    Warren :)

     

     

  • Sebastiaan Janssen 5060 posts 15522 karma points MVP admin hq
    Nov 19, 2009 @ 13:36
    Sebastiaan Janssen
    0

    Have you tried adding:

    <xsl:param name="currentPage"/>

    Before the 

    <xsl:template match="/">
  • Kim Andersen 1447 posts 2196 karma points MVP
    Nov 19, 2009 @ 13:40
    Kim Andersen
    0

    I can't see the $currentPage being defined in the included XSLT-file. Shouldn't it be there...

  • Warren Buckley 2106 posts 4836 karma points MVP 7x admin c-trib
    Nov 19, 2009 @ 13:40
    Warren Buckley
    0

    Yes if I do that though, it will work with the version being called directly from the macro, but now the ones that refrence it using the include now don't work.

    I get this error:

    Error loading XSLT Article/DisplayArticleGallery.xslt
    The variable or parameter 'currentPage' was duplicated with the same import precedence.
      at System.Xml.Xsl.XslCompiledTransform.LoadInternal(Object stylesheet, XsltSettings settings, XmlResolver stylesheetResolver)
      at System.Xml.Xsl.XslCompiledTransform.Load(XmlReader stylesheet, XsltSettings settings, XmlResolver stylesheetResolver)
      at umbraco.macro.CreateXsltTransform(XmlTextReader xslReader, Boolean debugMode)
      at umbraco.macro.getXslt(String XsltFile)
      at umbraco.macro.loadMacroXSLT(macro macro, Hashtable attributes, Hashtable pageElements)
  • Morten Bock 1867 posts 2140 karma points MVP 2x admin c-trib
    Nov 19, 2009 @ 13:43
    Morten Bock
    2

    I think you want to define your $currentPage before including the xslt:

    <!-- XSLT Template Includes -->
    <xsl:param name="currentPage"/>
    <xsl:include
    href="../Common/ToolboxLinks.xslt"/>
    <xsl:template match="/">
     
    <!-- Some other stuff & logic -->
     
    <!-- Article tools -->
     
    <xsl:call-template name="toolboxLinks" />
    </xsl:template>
  • Sebastiaan Janssen 5060 posts 15522 karma points MVP admin hq
    Nov 19, 2009 @ 13:49
    Sebastiaan Janssen
    0

    Ah of course.

    I think in that case I'd write an XSLT extension to reconstruct the currentPage variable in the second XSLT. If the $currentPage variable is null, then use the "currentPage" xml from the extension. I'm just not sure if you can test for null in XSLT?!

  • Sebastiaan Janssen 5060 posts 15522 karma points MVP admin hq
    Nov 19, 2009 @ 13:50
    Sebastiaan Janssen
    0

    Or you could use a third XSLT that only defines the currentPage param and includes the ToolboxLinks one. Then you could call it directly.

  • Adz 4 posts 32 karma points
    Nov 19, 2009 @ 13:54
    Adz
    1

    Hi mate,

     

    A couple of suggestions.

     

    1) Put the xsl:param name="currentPage" into the INCLUDED FILE (ToolBoxLinks.xslt) ONLY - do not put it in the calling file.  In theory that should work; its possible that Umbraco's validation at save may return an error, but ignore errors and try it anyway!  Because basically by including the file, the xsl:param is available to your main xslt file.  Pretty sure that should work.

     

    2) Alternatively, try using xsl:import instead of xsl:include.  That should also work.

     

    (For more info on the logic behind why that should work, read http://www.xml.com/pub/a/2000/11/01/xslt/index.html )

    3) Alternatively, modify your "toolboxLinks" template so it accepts a parameter, name "theCurrentPage" and pass it in from your main xsl file.

    Then create a third XSLT file which also includes the file, and passes $currentPage into theCurrentPage param.  But hopefully, 1 or 2 will work for you.

     

    All the best

     

    Adz.

  • Warren Buckley 2106 posts 4836 karma points MVP 7x admin c-trib
    Nov 19, 2009 @ 13:57
    Warren Buckley
    0

    Thanks Morten, I really thought that would solve it, but it didnt :(
    The included versions now work fine, but the direct macro version doesn't.

    I suppose that could be the last resort Sebastiaan to use another XSLT as like a proxy, but it's a shame if I can't just call the xslt include itself.

    Anyone else want to suggest anything?

    Warren

     

  • Warren Buckley 2106 posts 4836 karma points MVP 7x admin c-trib
    Nov 19, 2009 @ 14:05
    Warren Buckley
    0

    Excellent stuff Adz I tried your first suggestion by moving the <xsl:param name="currentPage"/> into the included XSLT file only and removing it from the other XSLT files that include/reference that XSLT file.

    Great stuff. Karma given :)

  • Peter Duncanson 430 posts 1360 karma points c-trib
    Nov 20, 2009 @ 15:47
    Peter Duncanson
    0

    XSL include get processed first when they are read in so they need any params you are going to use in templates to be defined in the include file.

    I'm a big fan of having a include file of helpers which can save global variables, functions etc. Makes life so much easier if you start coding from the off to allow for that.

    Pondering including a "helpers" XSL file in the best practise package I'm knocking together.

    Pete

  • Warren Buckley 2106 posts 4836 karma points MVP 7x admin c-trib
    Nov 24, 2009 @ 12:12
    Warren Buckley
    0

    Hiya guys,
    OK with Adz suggestion of moving the currentPage into the include worked fine until I updated my main XSLT with another include that will also work as a standalone macro.

    It works perfectly fine as standalone macros, but the problem again now is that both of the included XSLT files now have currentPage in.

    Suggestions again to get this to work please.

    Thanks,
    Warren :)

  • Warren Buckley 2106 posts 4836 karma points MVP 7x admin c-trib
    Nov 24, 2009 @ 12:32
    Warren Buckley
    0

    OK answering my own question - not ideally what I wanted to do but I added a wrapper XSLT file for the second item that was being included in the main XSLT file and pointed the macro to the wrapper file and not the included xslt file.

    An example wrapper file:

    <xsl:param name="currentPage" />

    <xsl:variable name="boxName" select="/macro/boxName" />
     
    <!-- XSLT Template Includes -->
    <xsl:include href="Sidebar_LinkBox.xslt"/>

    <xsl:template match="/">
        <xsl:call-template name="sidebarBox">
          <xsl:with-param name="boxName" select="$boxName" />
        </xsl:call-template>
    </xsl:template>

    Updated xslt include file (removed the <xsl:template match="/">)

    <xsl:template name="sidebarBox">
        <xsl:param name="boxName" />
        <xsl:param name="boxItem" select="$currentPage/ancestor-or-self::root/node [@nodeTypeAlias='Settings']//node [@nodeTypeAlias = 'SidebarLinkBox' and @nodeName = $boxName]" />
        
        <div>
          <xsl:attribute name="class">
            <xsl:choose>
              <xsl:when test="$boxItem/data[@alias='centerText'] = 1">
                <xsl:text>sidebar-box center</xsl:text>
              </xsl:when>
              <xsl:otherwise>
                <xsl:text>sidebar-box</xsl:text>
              </xsl:otherwise>
            </xsl:choose>
          </xsl:attribute>

          <xsl:if test="$boxItem/data[@alias='image'] !=''">
            <img class="float-left" alt="$boxItem/data[@alias='header']" src="{$boxItem/data[@alias='image']}"/>
          </xsl:if>
          
          <h3>
            <xsl:value-of select="$boxItem/data[@alias='header']"/>
          </h3>
          <p>
            <xsl:value-of select="$boxItem/data[@alias='bodyText']"/>        
          </p>
          <a class="arrow-button" href="{$boxItem/data[@alias='linkLocation']}">
            <span>
              <xsl:value-of select="$boxItem/data[@alias='linkText']" />
            </span>
          </a>
        </div>
      </xsl:template>
  • Peter Duncanson 430 posts 1360 karma points c-trib
    Nov 25, 2009 @ 19:34
    Peter Duncanson
    0

    That seems to me to be a perfectly valid and sensible solution Warren, why do you get a bad code smell?

Please Sign in or register to post replies

Write your reply to:

Draft