Copied to clipboard

Flag this post as spam?

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


  • adrianfriend 67 posts 68 karma points
    Sep 20, 2011 @ 20:28
    adrianfriend
    0

    Grouping by @nodeType

    Hi All,

    This has been driving me up the wall all day, I have 12 children nodes with varying @nodeType values (4 disctinct @nodeTypes) and would like to group them by this. For some reason it only returns data for two of these @nodeType values.

    <xsl:key name="groupByType" match="*[@isDoc]" use="string(@nodeType)"/>
    
    <xsl:for-each select="$centre/* [@isDoc and generate-id() = generate-id(key('groupByType', string(@nodeType))[1])]"> <xsl:value-of select="@nodeName"/> </xsl:for-each>

    If I take the generate-id() etc off I can list the nodes fine so I know the $centre variable has the right dataset.

    Please can anyone help?

    Adrian

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Sep 20, 2011 @ 21:33
    Chriztian Steinmeier
    0

    Hi Adrian,

    I've done a very similar thing - but instead of using the nodeType attribute, I used name() (should yield the same nodes, though) - but there *is* a nasty catch when using keys, which is that the key() function can only find nodes in the document that contains the "current context node" - and that can be a problem in Umbraco macros, if you're executing the macro inside the root template (match="/"). There's a couple of ways to work around this, so try the following and see if it works:

    <xsl:param name="currentPage" />
    <xsl:variable name="siteRoot" select="$currentPage/ancestor-or-self::root" />
    
    <!-- Index node by their DocumentType Alias -->
    <xsl:key name="groupByName" match="*[@isDoc]" use="name()" />
    
    <xsl:template match="/">
        <xsl:apply-templates select="$siteRoot" />
    </xsl:template>
    
    <xsl:template match="root">
        <xsl:for-each select="//*[@isDoc][count(. | key('groupByName', name())[1]) = 1]">
            <xsl:sort select="name()" />
    
            <!-- Header for current group -->
            <h1><xsl:value-of select="name()" /></h1>
    
            <!-- Process current group of nodes -->
            <xsl:for-each select="key('groupByName', name())">
                <xsl:sort select="@nodeName" />
    
                <xsl:value-of select="@nodeName" />
            </xsl:for-each>
    
        </xsl:for-each>
    </xsl:template>
    

    /Chriztian

  • adrianfriend 67 posts 68 karma points
    Sep 20, 2011 @ 22:23
    adrianfriend
    0

    Hi Chriztian,

    I tried what you suggested but still get the same results, I did try local-name() as well. Strange thing is if I try:

     [count(. | key('groupByName', name())[2]) = 1]

    it works fine with [2], don't quite understand that part. The nodes I want are not within the current site but off the root node (-1). Full code below just in case there is something I'm missing.

    <xsl:key name="groupByName" match="*[@isDoc]" use="name()"/>
      <xsl:template name="profiles">
        <!-- Because we are adding this xslt file to another we cant use the standard currentPage param-->
        <!-- Create a param to hold the currentPage that the calling Xslt passes in -->
        <xsl:param name="theCurrentPage"></xsl:param>
        <xsl:if test="$theCurrentPage/centerPage !=''">
          <xsl:call-template name="profileMatrix">
            <xsl:with-param name="node" select="$theCurrentPage"/>
          </xsl:call-template>
        </xsl:if>
      </xsl:template>

      <xsl:template name="profileMatrix">
        <xsl:param name="node"></xsl:param>
          <xsl:variable name="centre" select="/root/INTOProfiles/ProfileCentre [centre/MultiNodePicker/nodeId = $node/@id]"></xsl:variable>
          <xsl:for-each select="$centre/child::* [@isDoc][count(. | key('groupByName', name())[2]) = 1]">
            <xsl:sort select="name()" />
            <h1>
              <xsl:value-of select="name()" />
            </h1>
            <xsl:for-each select="key('groupByName', name())">
              <xsl:sort select="@nodeName" />

              <xsl:value-of select="@nodeName" />
            </xsl:for-each>
          </xsl:for-each>
      </xsl:template>

    Adrian

     

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Sep 20, 2011 @ 22:57
    Chriztian Steinmeier
    0

    Hi Adrian,

    OK - the [1] vs. [2] thing: As long as there is always at least 2 nodes of each type it doesn't matter - as long as we're only checking one of them. But if there's a doctype (nodeType) that only exists a single time, it will not be picked up...

    Now, on to your problem - are you sure you've tried exactly the code I pasted? It should find and group all the document types (off of root, yes).

    One thing you're doing in the profileMatrix template should be changed, though: You're selecting children of the $centre node, but you're using the full set from the key(), so if the first (or in this case second because of the [2] predicate) node in the key's result isn't in that branch of the site (not below $centre, that is) the "comparison" won't work... it effectively checks to see if the current node in the for-each is exactly the same node as the second node in the result from key(), which will never happen if the second node in the key() result isn't located in the same branch. Phew, I hope that makes just a little sense :-)

    OK, so you could probably resolve this by filtering the result from key() before testing, e.g.:

    <xsl:for-each select="$centre/*[@isDoc][count(. | key('groupByName', name())[../@id = $centre/@id][1]) = 1]">

    (and go back to using [1] again :-)

    Please let us know how i goes...

    /Chriztian

  • adrianfriend 67 posts 68 karma points
    Sep 20, 2011 @ 23:16
    adrianfriend
    0

    Chriztian,

    Firstly thanks for explaining the whole key() thing, made perfect sense :-)

    Just copied the filter code from above and worked like a dream.

    Thanks so much,

    Adrian

  • Chriztian Steinmeier 2798 posts 8788 karma points MVP 8x admin c-trib
    Sep 20, 2011 @ 23:19
    Chriztian Steinmeier
    0

    Good to hear, Adrian!

    /Chriztian

Please Sign in or register to post replies

Write your reply to:

Draft