Copied to clipboard

Flag this post as spam?

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


  • Bruce Clark 56 posts 80 karma points
    Nov 23, 2010 @ 01:08
    Bruce Clark
    0

    Multiple sites, xslt output starting from root, help .. please

    I've been trying to get this for a few hours, felt like it shoud be easy, it's not going well for me. Here's the deal.

    I have several sites in the top level of Umbraco (just under Content) because I am doing translations. I have a Page List macro that I've been using that targets a specific documentType property and then spits out the pages from underneath that node. For instance, I have a section called solutions, this has the pageAlias (as I've called it) of 'solutions'. It has 5 subpages under it. If I want to spit out these pages I can do it via the macro by making pageAliasSelect = solutions. My XSLT will go up to the root and then down until it finds that pageAlias. This works like a charm and has been great for a number of sites. The problem comes when I have two sites at the top level for translations.

    $currentPage/ancestor-or-self::root//* [@isDoc][string(pageAlias) = $pageAliasSelect]

    If I have the documentType property pageAlias in both sites it will spit out the pages from both sites. The answer, I assume, is to alter the above code to stop before hitting the top level. Basically I want to stop at level 2 (I think?) and then go downward from there searching for pageAlias.

    Is there a way to start looking through all nodes without going to the root? Thank you so MUCH! I am losing my mind over this.

    Cheers,

    Bruce

     

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Nov 23, 2010 @ 01:18
    Chriztian Steinmeier
    0

    Hi Bruce,

    Use this to get the current site's 'root':

    <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]" />

    Then you can do stuff like:

    $siteRoot//*[@isDoc][pageAlias = $pageAlias]

    /Chriztian

  • Bruce Clark 56 posts 80 karma points
    Nov 23, 2010 @ 06:32
    Bruce Clark
    0

    Thank you SO much!!! This worked. 

  • Bruce Clark 56 posts 80 karma points
    Nov 23, 2010 @ 06:59
    Bruce Clark
    0

    Actually, correction. This seems to be working unless I target the top lev el of the site. So, for a subpage of a specific site it works, but if I target the very top page it outputs nothing. 

    Any idea why that'd be happening? Ideally I really need a pageList that I can throw at anything. For instance, the one I posted in the first example works no matter what pageAlias I target. It will always spit out the subpages, and I can use it many many times depending on the page and subpages I need to work with. I've added leveling too, so it will spit out sub-levels if I need, for instance in a dropdown. 

    <?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="xml" omit-xml-declaration="yes" />

    <xsl:param name="currentPage"/>

    <!-- Following are parameters from the macro parameter -->
    <xsl:variable name="pageAliasSelect" select="/macro/pageAliasSelect"/>

    <!-- Set default values of the parameters if none exists -->
    <xsl:variable name="listSortOrder">
      <xsl:choose>
        <xsl:when test="string(/macro/listSortOrder) != ''">
          <xsl:value-of select="/macro/listSortOrder" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="'sortOrder'"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:variable name="maxLevel">
      <xsl:choose>
        <xsl:when test="string(/macro/maxLevel) != ''">
          <xsl:value-of select="/macro/maxLevel" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="'1'"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:variable name="topCount">
      <xsl:choose>
        <xsl:when test="string(/macro/topCount) != ''">
          <xsl:value-of select="/macro/topCount" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="'9999999999'"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:variable name="activeName">
      <xsl:choose>
        <xsl:when test="string(/macro/activeName) != ''">
          <xsl:value-of select="/macro/activeName" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="'active'"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:variable name="startLevel">
      <xsl:choose>
        <xsl:when test="string(/macro/startLevel) != ''">
          <xsl:value-of select="/macro/startLevel" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="'1'"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:variable name="includeParentNode">
      <xsl:choose>
        <xsl:when test="string(/macro/includeParentNode) != ''">
          <xsl:value-of select="/macro/includeParentNode" />
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="0"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>
    <!-- END macro parameters -->

    <!-- main template area -->
    <xsl:template match="/">

    <!-- call the template method: drawNodes -->
    <!-- run this if the start level is not greater than one -->
    <xsl:if test="$startLevel = 1">
      <xsl:call-template name="drawNodes">
      <!-- we want to start at the root node and look for the pageAlias specified from the template (pageAliasSelect) -->
      <xsl:with-param name="parentNode" select="$currentPage/ancestor::root//* [@isDoc][string(pageAlias) = $pageAliasSelect]"/>
    </xsl:call-template>
    </xsl:if>

    <xsl:if test="$startLevel &gt;= 2">  
      <xsl:call-template name="drawNodes">
      <!-- we want to start at the root node and go up until we hit the startLevel specified above -->
      <xsl:with-param name="parentNode" select="$currentPage/ancestor-or-self::* [@isDoc][@level=$startLevel]"/>
    </xsl:call-template>
    </xsl:if>

    <xsl:text>&#10;</xsl:text>

    </xsl:template>

    <!-- template method: drawNodes -->
    <xsl:template name="drawNodes">
    <!-- parent node variable -->
    <xsl:param name="parentNode"/>

    <xsl:text>&#10;&#9;</xsl:text>
    <ul class="autoclear">
      <xsl:text>&#10;</xsl:text>

    <!-- loop through the child nodes (/node) -->
    <xsl:for-each select="$parentNode/* [@isDoc][string(hideFromNavigation) != '1']">

      <xsl:variable name="visibleNodes" select="count($parentNode/* [@isDoc][string(hideFromNavigation) != '1'])"></xsl:variable>

    <!-- only continue if the record count is less than the topCount specified in the macro tag -->
    <xsl:if test="position() &lt;= $topCount">
      <xsl:text>&#9;&#9;</xsl:text>

    <!-- create a variable 'liClass', depending on what row, give it a specific class name -->
    <xsl:variable name="liClass">
      <xsl:choose>
        <xsl:when test="position() = 1">
          <xsl:value-of select="' first'"/>
        </xsl:when>
        <xsl:when test="position() = $visibleNodes">
          <xsl:value-of select="' last'"/>
        </xsl:when>
        <xsl:when test="(position() mod 2) = 0">
          <xsl:value-of select="' alt'"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="''"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <!-- if we need to label the <li> tag with an incremental number, use position() -->
    <li class="item{position()}{$liClass}">

    <!-- this sets the current page and toggles an active state -->
    <xsl:if test="$currentPage/ancestor-or-self::*/@id = current()/@id">
      <xsl:attribute name="id">
        <xsl:value-of select="$activeName"/>
      </xsl:attribute>
    </xsl:if>

    <!-- umbraco.library:NiceUrl returns the formatted url. More on umbraco.library: http://our.umbraco.org/wiki/reference/umbracolibrary -->
    <a href="{umbraco.library:NiceUrl(@id)}">
    <!-- if the navigationTitle alias was entered, use it instead of the nodeName -->
    <xsl:choose>
      <xsl:when test="navigationTitle != ''">
        <xsl:value-of select="navigationTitle"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="@nodeName"/>
      </xsl:otherwise>
    </xsl:choose>
    </a>

    <!-- if a maxLevel was specified too include sub-pages, run the 'drawNodes' template method again -->
    <xsl:if test="count(./* [@isDoc][string(./hideFromNavigation) != '1' and @level &lt;= $maxLevel]) &gt; 0">
      <xsl:call-template name="drawChildNodes">
        <xsl:with-param name="parentNode" select="."/>
      </xsl:call-template>
    </xsl:if>

    </li>

    <xsl:text>&#10;</xsl:text>
    </xsl:if>
    </xsl:for-each>
    <xsl:text>&#9;</xsl:text></ul>
    </xsl:template>


    <!-- template method: drawChildNodes -->
    <xsl:template name="drawChildNodes">
    <!-- parent node variable -->
    <xsl:param name="parentNode"/>

    <xsl:text>&#10;&#9;</xsl:text>
    <ul>
      <xsl:text>&#10;</xsl:text>

    <!-- If includeParentNode is 1, then output the current node before the child nodes -->
    <xsl:if test="$includeParentNode = 1">
      <xsl:if test="$parentNode/showDropDownOverview != '0'">
        <li>
          <a href="{umbraco.library:NiceUrl($parentNode/@id)}">
          <!-- if the navigationTitle alias was entered, use it instead of the nodeName -->
          <xsl:choose>
            <xsl:when test="$parentNode/dropDownName != ''">
              <xsl:value-of select="$parentNode/dropDownName"/>
            </xsl:when>
            <xsl:when test="$parentNode/navigationTitle != ''">
              <xsl:value-of select="$parentNode/navigationTitle"/>
            </xsl:when>
            <xsl:otherwise>
              <xsl:value-of select="$parentNode/@nodeName"/>
            </xsl:otherwise>
          </xsl:choose>
        </a>
      </li>
    </xsl:if>
    </xsl:if>

    <!-- loop through the child nodes (/node) -->
    <xsl:for-each select="$parentNode/* [@isDoc][string(hideFromNavigation) != '1']">

      <xsl:variable name="visibleNodes" select="count($parentNode/* [@isDoc][string(hideFromNavigation) != '1'])"></xsl:variable>

    <!-- only continue if the record count is less than the topCount specified in the macro tag -->
    <xsl:if test="position() &lt;= $topCount">
      <xsl:text>&#9;&#9;</xsl:text>

    <!-- create a variable 'liClass', depending on what row, give it a specific class name -->
    <xsl:variable name="liClass">
      <xsl:choose>
        <xsl:when test="position() = 1">
          <xsl:value-of select="'first'"/>
        </xsl:when>
        <xsl:when test="position() = $visibleNodes">
          <xsl:value-of select="'last'"/>
        </xsl:when>
        <xsl:when test="(position() mod 2) = 0">
          <xsl:value-of select="'alt'"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="''"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>


    <!-- if we need to label the <li> tag with an incremental number, use position() -->
    <li>

    <!-- this sets the current page and toggles an active state -->
    <xsl:if test="$currentPage/ancestor-or-self::*/@id = current()/@id">
      <xsl:attribute name="id">
        <xsl:value-of select="$activeName"/>-<xsl:value-of select="@level - $startLevel" disable-output-escaping="yes"/>
      </xsl:attribute>
    </xsl:if>

    <!-- umbraco.library:NiceUrl returns the formatted url. More on umbraco.library: http://our.umbraco.org/wiki/reference/umbracolibrary -->
    <a href="{umbraco.library:NiceUrl(@id)}">
    <!-- if the navigationTitle alias was entered, use it instead of the nodeName -->
    <xsl:choose>
      <xsl:when test="navigationTitle != ''">
        <xsl:value-of select="navigationTitle"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="@nodeName"/>
      </xsl:otherwise>
    </xsl:choose>
    </a>

    <!-- if a maxLevel was specified to include sub-pages, run the 'drawNodes' template method again -->
    <xsl:if test="count(./* [@isDoc][string(./hideFromNavigation) != '1' and @level &lt;= $maxLevel]) &gt; 0">
      <xsl:call-template name="drawChildNodes">
        <xsl:with-param name="parentNode" select="."/>
      </xsl:call-template>
    </xsl:if>
    </li>

    <xsl:text>&#10;</xsl:text>
    </xsl:if>
    </xsl:for-each>
    <xsl:text>&#9;</xsl:text></ul>
    </xsl:template>


    </xsl:stylesheet>

  • Bruce Clark 56 posts 80 karma points
    Nov 23, 2010 @ 18:38
    Bruce Clark
    0

    Any help on this? I'm still stuck. Not sure why the posted solution won't work for the first level. 

  • Tom Fulton 2030 posts 4998 karma points c-trib
    Nov 23, 2010 @ 19:28
    Tom Fulton
    0

    Hi Bruce,

    A little confused on exactly what the problem is - but at first glance I would ask, what is $startLevel set to in the case you are describing?  If its >= 2 it won't match anything since there wont be any ancestors with @level=2 when you are at level 1.

    If its 1, I don't see anything obvious preventing it from working.  To debug try to find out where it's stopping at and dump out the XML to make sure it matches what you are expecting:  <textarea><xsl:copy-of select="..your xpath.."/></textarea>

    -Tom

     

  • Bruce Clark 56 posts 80 karma points
    Nov 23, 2010 @ 20:01
    Bruce Clark
    0

    I am really just using StartLevel to determine what the user is doing with the Macro. In instances where it's two or greater I know to show pages in relation to the current page. When it's one then it needs to default to the targeted page via $pageAliasSelect. Here's the issue, if I am targeting the top level page of the site, almost always called Home, I can output subpages with this command:

    $currentPage/ancestor::root//* [@isDoc][string(pageAlias) = $pageAliasSelect]

    I add pageAliasSelect="home" in the macro and it will give me the pages right under the Home page of the site, in the example below it would output all the first level subpages.

    - Home (pageAlias='home')
       - Subpage 1
       - Subpage 2 (pageAlias='sub2')
          - Sub-subpage 1
          - Sub-subpage 2
          - Sub-subpage 3
       - Subpage 3
       - Subpage 4

    I could also target pageAliasSelect='sub2' and get all the pages from that (Sub-subage 1, Sub-subapge 2, etc.). It's very reusable if I need to get pages from anywhere on the site.

    In the fix that Chriztian gave: 

    <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::*[@level = 1]" />

    $siteRoot//*[@isDoc][pageAlias = $pageAlias]

    the call to get subapges of pageAliasSelect='sub2' will work perfectly. However, I can no longer the pages from pageAliasSelect='home'. It won't output anything. I was wondering why that is and if I can modify Chriztians solution to work with the top page of a site.

    Keep in mind, the reason I need to change from the first example is because I am now using multiple sites (for translations) and the top example will spit out pages from all sites whereas Chriztian's fix will only spit out pages from the current site.

    Thanks so much.

    -Bruce

  • Tom Fulton 2030 posts 4998 karma points c-trib
    Nov 23, 2010 @ 20:16
    Tom Fulton
    0

    Going by the last snippet you pasted, the $siteRoot is going to get you the XML starting at the "Home" node, and the second statement is going to get everything under the Home node (not including the Home node itself).  So there wouldnt be any matching nodes under Home with a pageAlias of home (according to your structure anyway).

    You could make it match the Home node by using

    $siteRoot//descendant-or-self::* [@isDoc][pageAlias = $pageAlias]

    I might still be way off base as I'm still a bit confused, but hopefully this helps :)

     

  • Bruce Clark 56 posts 80 karma points
    Nov 24, 2010 @ 03:34
    Bruce Clark
    0

    Thank you, so much. This is exactly what I needed. Just couln't think about it the right way.

  • Fourfinger 24 posts 44 karma points
    Feb 24, 2012 @ 10:52
    Fourfinger
    0

    Just came to say thanks! Chriztian's solution works!

Please Sign in or register to post replies

Write your reply to:

Draft