Copied to clipboard

Flag this post as spam?

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


  • Claushingebjerg 939 posts 2574 karma points
    Mar 31, 2009 @ 12:25
    Claushingebjerg
    0

    List entire structure from changeable source

    Im trying to do some menu stuff where i want to list a node structure from a changeable source on a macro. Im building on the sitemap xslt, but have a bit of a problem changing the source from $currentpage to my macro's $source. $source is a content picker

    [code]






    • Stephan Lonntorp 195 posts 212 karma points
      Mar 31, 2009 @ 13:02
      Stephan Lonntorp
      0

      your content picker only contains a node id, you'll have to use

    • Claushingebjerg 939 posts 2574 karma points
      Mar 31, 2009 @ 13:16
      Claushingebjerg
      0

      ok, but changing that doesnt really list the substructure form the source, but from level1... Any ideas?

      [code]






      • Douglas Robar 3570 posts 4711 karma points MVP ∞ admin c-trib
        Mar 31, 2009 @ 14:08
        Douglas Robar
        0

        Change this line [code][/code]

        to

        [code][/code]

        cheers,
        doug.

      • Claushingebjerg 939 posts 2574 karma points
        Mar 31, 2009 @ 16:03
        Claushingebjerg
        0

        Im totally lost :)

        drobar, doing what you suggest returns nothing

        [code]

        [/code]

        But if i do

        [code]

        [/code]

        it returns the root level of my $source. But the goal is to get a nested list with subpages as well.
        My complete xslt is below, if anyone can spot any errors :), thanks


        [code]














        [/code]

      • Douglas Robar 3570 posts 4711 karma points MVP ∞ admin c-trib
        Mar 31, 2009 @ 21:49
        Douglas Robar
        2

        Feeling lost? No problem! Time for some theory and some code. (Please forgive me if I explain stuff you already understand, but if I don't give enough detail then just ask)

        The first thing to do is define what you want to do. I think you're trying to create a nested UL/LI list for your website, starting at whatever node is selected (and passed in) with a Content Picker on your macro.

        Starting with the sitemap.xslt template is a great way to go. But let's build this from the ground up ourselves so it is clear what is happening at every stage. That will also make it easier for you to modify it if my sample doesn't meet your needs exactly.

        The first thing to do is start with a basic xslt file. Basically, everything outside the block. That code is standard and there isn't much to do there except add a variable to the macro parameter:

        [code] [/code]

        (Later on you might want a variable to specify how deep to go in the content tree but for now we'll just list EVERY node below the source node, no matter how many levels down the tree it is)

        Remember that the Content Picker data type contains a node ID. You will have to convert that ID into a real node to loop through its children. This is done with the umbraco.library:GetXmlNodeById() function.

        Once we have the node we can get any of the usual properties, such as its name, create date, etc. Let's prove that with this simple bit of code that will print out the node name for the selected source node:

        [code][/code]

        Now that we've got the source node, we want to list all its immediate children in a UL list. This is done by using an xsl:for-each loop and selecting the source's child nodes:

        [code]




        [/code]

        But if one of these nodes also has children below it we would need to manually create the UL/LI structure in the xslt macro... and keep it up to date whenever there is a change to the site structure. That won't do.

        Instead, we want to create what would be called a "function" in other languages to make as many embedded UL/LI lists as needed. In xslt, we simply create another template, give it a name, and then call that named template. Just like with functions in other languages, we can pass parameters in to the named xslt template.

        The sitemap.xslt file used the name 'drawNodes' so we'll do the same. We want this "function" to take a starting node and create a UL/LI list. If any of the items has children below it we want to call the drawNodes template again with THAT node so that all its children get listed as well. We'll continue to call drawNodes until we've gone through all the nodes below the original $source node.

        Let's see how that's done, but step-by-step.

        First, we'll re-write our last xslt sample to use a named template and we'll call that template. The output will be the same but we'll have a framework in place to make further logic modifications:

        [code]

        [/code]

        As I said, the output of this code sample and the one before it are the same. Which means it still only shows the children of the original source node.

        Let's add some logic to call the drawNodes template as many times as necessary, for as many children, grandchildren, great-grandchildren, etc. your site has. All we need to do is check to see if the current node being displayed has any children. If it does, we call the drawNodes template again, and presto we have a nested UL/LI list of all the nodes:

        [code]

        [/code]

        There you have it, a nested UL/LI list of all the nodes below the original $source node.

        Of course, you can embellish this code to include href's instead of simply printing the node names:
        [code]




      • [/code]

        And you could add various tests to limit the number of levels to display, as well as being sure not to display any node that has the umbracoNaviHide property set. You might also check that you only show pages that are either not protected or which are protected but are accessible by the currently logged in user.

        When you add all of these additions you'll find that you are very close to the code in the sitemap.xslt file you started with. But now you understand why every line is there and what it is doing.

        I hope this helps. Be sure to ask if anything is unclear.

        cheers,
        doug.

      Copy Link
    • Stephan Lonntorp 195 posts 212 karma points
      Apr 01, 2009 @ 01:02
      Stephan Lonntorp
      0

      Doug, you're the man. This was so much more comprehensive than any post I've ever seen. You're an asset and an inspiration to us all.

      Copy Link
    • Claushingebjerg 939 posts 2574 karma points
      Apr 01, 2009 @ 16:20
      Claushingebjerg
      0

      Thanks Douglas.

      I can't believe the lengths you went to make me understand this. Im really greatful.

      This post should go somewhere into some documentation. It really opened my eyes much more to this xslt stuff, i find so hard to comprehend.

      Thanks again. :d/

      Copy Link
    • dygfloyd 13 posts 24 karma points
      Apr 11, 2009 @ 20:46
      dygfloyd
      0

      I just read this topic and it solved 2 or 3 problems for me too. Great post, Doug!

      Copy Link
    • Garrett Fisher 341 posts 496 karma points
      Sep 11, 2009 @ 22:42
      Garrett Fisher
      0

      Yeah that post rocked everyone's world, especially those new to Umbraco and XSLT.  Question for you, Doug-- what if I just wamted to specify, as you alluded to early in the thread, the depth of the structure in which to delve?  I only want to display the first two tiers....

      Thanks,

      Garrett

      Copy Link
    • Ron Brouwer 273 posts 768 karma points
      Sep 12, 2009 @ 12:50
      Ron Brouwer
      0

      You can change:

      <xsl:if test="count(./node) &gt; 0">

      Into

      <xsl:if test="count(./node) &gt; 0 and @level &lt; [the level where you want to stop]">

      Ron

      Copy Link
    • Ron Brouwer 273 posts 768 karma points
      Sep 12, 2009 @ 12:55
      Ron Brouwer
      1

      You can also use the folowing:

      <xsl:template match="/">
         
      <xsl:call-template name="drawNodes">
             
      <xsl:with-param name="parent" select="umbraco.library:GetXmlNodeById($source)" />
              <xsl:with-param name="levelsToGo" select="number(2)" />
          </xsl:call-template>
      </xsl:template>

      <xsl:template name="drawNodes">
         
      <xsl:param name="parent" />
      <xsl:param name="levelsToGo" />
          <ul>
         
      <xsl:for-each select="$parent/node">
             
      <li>
                 
      <xsl:value-of select="@nodeName" />
                 
      <xsl:if test="count(./node) &gt; 0 and $levelsToGo != 0">
                     
      <!-- this node has children, let's list them also -->
                     
      <xsl:call-template name="drawNodes">
                         
      <xsl:with-param name="parent" select="." />
                          <xsl:with-param name="levelsToGo" select="$levelsToGo - 1" />
                      </xsl:call-template>
                 
      </xsl:if>
             
      </li>
         
      </xsl:for-each>
         
      </ul>
      </xsl:template>

      Ron

       

      Copy Link
    • Garrett Fisher 341 posts 496 karma points
      Sep 14, 2009 @ 15:49
      Garrett Fisher
      0

      Thanks for the reply.  But this change makes everything disappear because I don't think @level has a value.  How would the page (or routine) know what level it's on if I don't set it?

       

      Regards,

      Garrett

      Copy Link
    • Ron Brouwer 273 posts 768 karma points
      Sep 14, 2009 @ 21:58
      Ron Brouwer
      0

      I you want to understand how @level works, take a look in "data/umbraco.config" thats the file where you are reading from.
      However you can use my second option (I prefer that method)

      I havent tested it but I think it should work.
      Let me know how it goes.

      Ron

      Copy Link
    • Garrett Fisher 341 posts 496 karma points
      Sep 21, 2009 @ 21:00
      Garrett Fisher
      0

      That worked great for me-- thanks so much!

       

      //Garrett

      Copy Link
    • Please Sign in or register to post replies

      Write your reply to:

      Draft