Copied to clipboard

Flag this post as spam?

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


  • David Conlisk 432 posts 1008 karma points
    May 26, 2010 @ 16:27
    David Conlisk
    0

    4.1 schema - issue selecting nodes

    Hi all.

    This works great:

    <xsl:variable name="RHSItemNode" select="$currentPage/RHSItemPickerCC"/>

    It gives the the child RHSItemPickerCC in my $RHSItemNode variable. Lovely.

    However, now I want to set RHSItemNode to be either $currentPage/RHSItemPickerCC, if it exists, or $currentPage/RHSItemPickerGA if it doesn't . I am trying this:

    <xsl:variable name="RHSItemNode">
        <xsl:choose>
          <xsl:when test="count($currentPage/RHSItemPickerCC) = 1">
            <xsl:copy-of select="$currentPage/RHSItemPickerCC"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:copy-of select="$currentPage/RHSItemPickerGA"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>

    When I output the results of each method each using <xsl:copy-of select="$RHSItemNode"/> I get the same markup for both as expected. BUT when I do this:

    <xsl:variable name="count" select="count($RHSItemNode/item)"/>

    It breaks for the second method of setting $RHSItemNode. I'm aware of the node-set function, but I don't understand why I would need it in this situation.

    How can I set RHSItemNode correctly? What am I missing here?

    Thanks,

    David

  • Sebastiaan Janssen 5060 posts 15522 karma points MVP admin hq
    May 26, 2010 @ 16:31
    Sebastiaan Janssen
    0

    Maybe obvious, could "count" be a reserved word? Try "counter" in the variable name instead.

  • David Conlisk 432 posts 1008 karma points
    May 26, 2010 @ 16:37
    David Conlisk
    0

    Hi Sebastiaan,

    Thanks for the suggestion but that line works fine when I set RHSItemNode using the first method above. The problem is that when I set the variable using the second method, it throws an error - the usual one - when I try to count the nodes:

    Error parsing XSLT file: \xslt\RHSItems.xslt  

    Cheers,

    David

  • webmonger 130 posts 285 karma points
    May 26, 2010 @ 16:44
    webmonger
    0

    Try using value-of instead of copy of. I had an odd issue that revolved around using copy-of reciently.

    Jon

  • Sebastiaan Janssen 5060 posts 15522 karma points MVP admin hq
    May 26, 2010 @ 16:55
    Sebastiaan Janssen
    1

    David, you can easily debug you XSLT files while running them as well, just attach Visual Studio to the worker process and VS will break on any errors thrown by XSLT, the error message you would get should provide you with some more information.

  • David Conlisk 432 posts 1008 karma points
    May 26, 2010 @ 17:06
    David Conlisk
    0

    @Jon - yeah I tried that too but I've found that when working with nodesets using copy-of works best - so far at least :) Using value-of in this situation doesn't seem to make any difference.

    @Sebastiaan - I'd forgotten about that - thanks for the tip! The current project doesn't have any .NET in it (yet) and so I'd forgotten about that feature. However, it doesn't seem to be throwing any errors for me in VS. The xslt files I'm editing in a different directory and using post-build events to copy them to the webroot. Could this be the reason for debugging not working?

     

  • Casey Neehouse 1339 posts 483 karma points MVP 2x admin
    May 26, 2010 @ 17:10
    Casey Neehouse
    1

    look at using msxsl node-set command

  • Sebastiaan Janssen 5060 posts 15522 karma points MVP admin hq
    May 26, 2010 @ 17:11
    Sebastiaan Janssen
    0

    Nah, VS will use the runtime files, but I'm not very familiar with other setups than my own. If you'd be willing to set it up like that blog post, you might have a bit more luck. :-)

  • Casey Neehouse 1339 posts 483 karma points MVP 2x admin
    May 26, 2010 @ 17:16
    Casey Neehouse
    0

    Another thought:

    <xsl:variable name="count" select="count($RHSItemNode//item)"/>

    use the descendant selector ("//") instead of child, as you are possibly not getting anything due to the xpath not matching.

     

  • David Conlisk 432 posts 1008 karma points
    May 26, 2010 @ 17:30
    David Conlisk
    0

    Thanks to everyone for their input. However, I'm still stumped. Outputting the results of both the first and second method of creating the variable (as per the original post) result in the exact same output:

    <textarea>
        <xsl:copy-of select="$RHSItemNode"/>
      </textarea>

     

    gives me:

    <RHSItemPickerCC id="1493" parentID="1128" level="5" writerID="0" creatorID="0" nodeType="1492" template="0" sortOrder="4" createDate="2010-05-25T10:59:35" updateDate="2010-05-26T16:11:15" nodeName="RHSItems" urlName="rhsitems" writerName="Administrator" creatorName="Administrator" path="-1,1222,1045,1140,1128,1493" isDoc="">
    <umbracoNaviHide>1</umbracoNaviHide>
    <heading>Contacts</heading>
    <item>1576</item>
    <heading>RSS</heading>
    <item>1580</item>
    <heading>Customer Case Studies</heading>
    <item>1420</item>
    <heading>My Blog</heading>
    <item>1491</item>
    </RHSItemPickerCC>

     

    What I'm trying to understand is why if both variables have the same value, that one causes the count statement to break, and the other doesn't?

    Here is a reduced version of my xslt to illustrate exactly what I'm up to (with standard umbraco xslt stuff removed):

    <xsl:template match="/">

      <!-- get the child RHS Item Picker for this page -->
      <xsl:variable name="RHSItemNode_METHOD1" select="$currentPage/RHSItemPickerCC"/>

      <xsl:variable name="RHSItemNode_METHOD2">
        <xsl:choose>
          <xsl:when test="count($currentPage/RHSItemPickerCC) = 1">
            <xsl:copy-of select="$currentPage/RHSItemPickerCC"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:copy-of select="$currentPage/RHSItemPickerGA"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>

      <!-- BOTH TEXTAREAS DISPLAY EXACTLY THE SAME CONTENTS! -->
      <textarea>
        <xsl:copy-of select="$RHSItemNode_METHOD1"/>
      </textarea>

      <textarea>
        <xsl:copy-of select="$RHSItemNode_METHOD2"/>
      </textarea>

      <!-- THIS WORKS! -->
      <xsl:variable name="myCount_1" select="count($RHSItemNode_METHOD1/item)"/>
     
      <!-- BUT THIS BREAKS! WTF? -->
      <xsl:variable name="myCount_2" select="count($RHSItemNode_METHOD2/item)"/>

    </xsl:template>

     

    Cheers,

    David

  • Morten Bock 1867 posts 2140 karma points MVP 2x admin c-trib
    May 26, 2010 @ 17:36
    Morten Bock
    1

    Using the copy-of will basically just give you some xml. What you want is a node set, so I would look in to expressing you logic in a single xpath statement instead of having the the xsl:choose element.

    Will have a play with it and see what I can come up with.

  • David Conlisk 432 posts 1008 karma points
    May 26, 2010 @ 17:55
    David Conlisk
    0

    Okay the node-set function works as a work-around as Casey mentioned, although I'm puzzled that you can't create a node set using the

    <xsl:variable ...>
    <xsl:choose>...</xsl:choose>
    </xsl:variable>

    syntax.

    The workaround should you require it is (further to the sample code in my last post):

    <xsl:variable name="myCount_2" select="count(msxml:node-set($RHSItemNode_METHOD2)/item)"/>

     

    If anyone knows how to create a node set so you don't need to use msxml:node-set function - I'd love to hear how!

    Thanks,

    David

     

  • David Conlisk 432 posts 1008 karma points
    May 26, 2010 @ 17:57
    David Conlisk
    0

    @Morten - Meant to add thanks for the explanation, makes things a little clearer in my addled brain :)

  • Morten Bock 1867 posts 2140 karma points MVP 2x admin c-trib
    May 26, 2010 @ 18:00
    Morten Bock
    0

    Try this:

        <xsl:variable name="RHSItemNode" select="$currentPage/RHSItemPickerCC[count($currentPage/RHSItemPickerCC) &gt; 0] | $currentPage/RHSItemPickerGA[count($currentPage/RHSItemPickerCC) = 0]" />

    It basically does a join on the two expressions, which have opposite [] constraints after them. So you get one or the other.

  • David Conlisk 432 posts 1008 karma points
    May 26, 2010 @ 18:09
    David Conlisk
    0

    Thanks @Morten - that works a treat! Do you know how to change it so that it's recursive?

    Each node in the site can have ONLY ONE of EITHER RHSItemPickerCC OR RHSItemPickerGA - and I want to recurse and use the FIRST of EITHER type that I find.

    Is this possible? I know how to recurse to get the first CC or GA item, but not how to say use the first of either that I find...

  • Morten Bock 1867 posts 2140 karma points MVP 2x admin c-trib
    May 26, 2010 @ 18:11
    Morten Bock
    0

    Hmm. I will take up the challenge while watching the status bars on my installing machine :-)

  • Morten Bock 1867 posts 2140 karma points MVP 2x admin c-trib
    May 26, 2010 @ 18:33
    Morten Bock
    1

    Ok, I made it a two step thing. First get the closest node that has one of the two elements, and the select the one that exists:

        <xsl:variable name="ContainingRHSItemNode" select="$currentPage/ancestor-or-self::node()[RHSItemPickerCC or RHSItemPickerGA][1]" />
        <xsl:variable name="RHSItemNode" select="$ContainingRHSItemNode[RHSItemPickerCC]/RHSItemPickerCC | $ContainingRHSItemNode[RHSItemPickerGA]/RHSItemPickerGA"/>
    
  • Morten Bock 1867 posts 2140 karma points MVP 2x admin c-trib
    May 26, 2010 @ 18:46
    Morten Bock
    1

    Or if you want the first one that has text in it:

        <xsl:variable name="ContainingRHSItemNode" select="$currentPage/ancestor-or-self::node()[RHSItemPickerCC != '' or RHSItemPickerGA != ''][1]" />
        <xsl:variable name="RHSItemNode" select="$ContainingRHSItemNode[RHSItemPickerCC != '']/RHSItemPickerCC | $ContainingRHSItemNode[RHSItemPickerGA != '']/RHSItemPickerGA"/>
    
  • David Conlisk 432 posts 1008 karma points
    May 26, 2010 @ 18:57
    David Conlisk
    0

    Morten that's fantastic!

    But I'm going to keep pushing :)

    How about if I want the first one that has at least one item child node? I've tried a variety of things along the lines of

      <xsl:variable name="ContainingRHSItemNode" select="$currentPage/ancestor-or-self::node()[RHSItemPickerCC[count(/item) &gt; 0] or RHSItemPickerGA[count(/item) &gt; 0]][1]" />
      <xsl:variable name="RHSItemNode" select="$ContainingRHSItemNode[RHSItemPickerCC]/RHSItemPickerCC[count(/item) &gt; 0] | $ContainingRHSItemNode[RHSItemPickerGA]/RHSItemPickerGA[count(/item) &gt; 0]"/>

    But no joy - one last one perhaps? How are those status bars - surely not finished just yet ;)

    Thanks!

  • Morten Bock 1867 posts 2140 karma points MVP 2x admin c-trib
    May 26, 2010 @ 19:03
    Morten Bock
    0

    I do like a challenge :-) Status bars still working...

  • Morten Bock 1867 posts 2140 karma points MVP 2x admin c-trib
    May 26, 2010 @ 19:07
    Morten Bock
    1

    This should get you the first one that has a non-empty item child node:

        <xsl:variable name="ContainingRHSItemNode" select="$currentPage/ancestor-or-self::node()[RHSItemPickerCC/item != '' or RHSItemPickerGA/item != ''][1]" />
        <xsl:variable name="RHSItemNode" select="$ContainingRHSItemNode[RHSItemPickerCC/item != '']/RHSItemPickerCC | $ContainingRHSItemNode[RHSItemPickerGA/item != '']/RHSItemPickerGA"/>
    
  • David Conlisk 432 posts 1008 karma points
    May 27, 2010 @ 09:49
    David Conlisk
    0

    Hey Morten,

    Great work mate, thanks very much. Each step you've given works as expected and hopefully having them here will help others having similar requirements. It's certainly helped me to improve my understanding of XPATH queries!

    Thanks again,

    David

Please Sign in or register to post replies

Write your reply to:

Draft