Copied to clipboard

Flag this post as spam?

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


  • John C Scott 473 posts 1183 karma points
    Dec 05, 2011 @ 12:57
    John C Scott
    0

    recursive embedded content

    loving this embedded content control so much :)

    for a specific problem I had to mess about a bit making this work so I thought I'd share the working code

    I have some embeedded content and if no selections are made then I need to take the selections from the parent page or parent page above that, in this case it's for a set of "rotating" banners and if no banners are chosen for the current page then use the banners set for the parent (unless this has no banners set, so then use those set on the parent of that etc.) all the way back to home which we can assume does have some set

    the normal "empty" approach doesn't necessarily work as there may or may not be item/ so I am using a count of item and then getting the first result (as the ancestor-or-self will return all up to home but I want the one closest to self)

    so the code I got to is:

      <xsl:variable name="recursiveBanner" select="($currentPage/ancestor-or-self::*/banner [count(data/item) &gt; 0 ])[1]"/>
      <ul>
      <xsl:for-each select="$recursiveBanner/data/item">
        <li>
          <xsl:variable name="mediaId" select="number(bannerImage)" />
          <xsl:if test="$mediaId > 0">
              <xsl:variable name="mediaNode" select="umbraco.library:GetMedia($mediaId, 0)" />
              <xsl:if test="$mediaNode/umbracoFile">
                  <img src="{$mediaNode/umbracoFile}" alt="{bannerText}" height="{umbracoHeight}" width="{umbracoWidth}" />
              </xsl:if>
          </xsl:if>
          <xsl:value-of select="bannerText"/></li>
      </xsl:for-each>
      </ul>

    but if anyone else can see a better way then very interested too :)

     

     

  • John C Scott 473 posts 1183 karma points
    Dec 15, 2011 @ 10:52
    John C Scott
    0

    so I had a problem with this

    what I found was that I am not getting ancestor-or-self in reverse document order, not sure why

    via Twitter I got some help from @greystate

     

    Chriztian Steinmeier
    greystate Chriztian Steinmeier 
    @ 
    @johncscott [1/2] - So you can reverse sort them using the level attribute if you have them in a variable... Makes sense?
     
     
     
    Chriztian Steinmeier
    greystate Chriztian Steinmeier 
    @ 
    @johncscott ancestor-or-self::*[1] will take the closest, but if you put them in a variable and later do $var[1] you'll get the topmost

    12 hours ago 

     

    Aaah so @level ?

    Can I put that in the XPATH or does it need to be in a separate xsl:sort?

     

     

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Dec 15, 2011 @ 11:29
    Chriztian Steinmeier
    1

    Hi John,

    The trick to know with this is that there's a difference between using a positional predicate (e.g. [2]) *as part of the XPath using the axis*, and using it on a variable/parameter (these contains node sets, which are always in "document order").

    Examples:

     

    Home
       News
          First Item
          Next Item

    Let's pretend $currentPage is at "Next Item".

    Set a variable to grab $currentPage and its ancestors:

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

    Now take the first in that set:

    <xsl:value-of select="$breadCrumbNodes[1]/@nodeName" />

    Which will give you "Home"

    But if you do it all in the value-of it'll give you something else:

    <xsl:value-of select="$currentPage/ancestor-or-self::*[@isDoc][1]/@nodeName" /> 

    - here you get "Second Item"... (!)

    So, to use them in the order you want, you can use the @level attribute that all Umbraco nodes have, and these will have their own unique value:

    <xsl:for-each select="$breadCrumbNodes">
    <xsl:sort select="@level" data-type="number" order="descending" />
    <!-- Do something -->
    </xsl:for-each>

    Hope that helps - otherwise, you know my number :-)

    /Chriztian

     

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 7x admin c-trib
    Dec 15, 2011 @ 11:30
    Chriztian Steinmeier
    1

    - and no, you can't include the sorting in the XPath :-(

  • John C Scott 473 posts 1183 karma points
    Dec 13, 2012 @ 03:13
    John C Scott
    0

    i've been looking at this again

    but instead now I am using a Multi Node Tree Picker control rather than the embedded content

    it has not quite worked

    a document property is inherited by all page which is 
    an MNTP data type for a "logo picker" I have a "Media" select tree type, it starts in a "client logos" media "folder" and has an xpath filter of /*
    this allows the user to pick some logos to show on the page with an article
    if the article has a parent (ie belongs to a section) and a logo selection is made for a parent
    but the current node does not have any items picked (ie count of items is zero)
    then it will use the logos selected for the parent

    this works nicely for the user

    however the xslt is not quite working out

    this is what I have:

    logo-recursive.xslt

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#x00A0;"> ]> <xsl:stylesheet version="1.0" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxml="urn:schemas-microsoft-com:xslt" xmlns:umbraco.library="urn:umbraco.library" xmlns:ucomponents.cms="urn:ucomponents.cms" exclude-result-prefixes="msxml umbraco.library ucomponents.cms ucomponents.media ucomponents.nodes"> <xsl:output method="xml" omit-xml-declaration="yes"/> <xsl:param name="currentPage"/> <xsl:variable name="recursiveLogoNodeId"> <xsl:call-template name="IterateLogo"> <xsl:with-param name="node" select="$currentPage" /> </xsl:call-template> </xsl:variable> <xsl:template match="/"> <xsl:if test="$currentPage/logoHide"> <xsl:variable name="recursiveLogoNode" select="umbraco.library:GetXmlNodeById($recursiveLogoNodeId)" /> <h4><xsl:value-of select="$recursiveLogoNode/logoLabel"/> </h4> <ul class="brends-box"> <xsl:for-each select="$recursiveLogoNode/logoPicker/MultiNodePicker/nodeId"> <xsl:variable name="mediaId" select="number(.)" /> <xsl:if test="$mediaId > 0"> <xsl:variable name="mediaNode" select="umbraco.library:GetMedia($mediaId, 0)" /> <xsl:if test="$mediaNode/umbracoFile != ''"> <li> <a href="#"> <img src="{$mediaNode/umbracoFile}" alt="{@nodeName}" /> </a> </li> </xsl:if> </xsl:if> </xsl:for-each> </ul> </xsl:if> </xsl:template> <xsl:template name="IterateLogo"> <xsl:param name="node" /> <xsl:choose> <xsl:when test="$node/@level = 1 or $node/logoPicker [count(MultiNodePicker/nodeId) &gt; 0 ]"> <xsl:value-of select="$node/@id" /> </xsl:when> <xsl:otherwise> <xsl:call-template name="IterateLogo"> <xsl:with-param name="node" select="$node/parent::*" /> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> 

     

    But this is not reliable

    Sometimes it does not show the logos collection from the right level.

    Can you see the error of my ways?

     

     

     

Please Sign in or register to post replies

Write your reply to:

Draft