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
    Jun 27, 2012 @ 22:36
    John C Scott
    0

    getting first child only

    I have a doc type that can include itself in the structure many levels deep inside itself. It represents a festival event crew / team structure. So if there was an event called "SomerFest" and everyone works for Michael, and Michael employs Tori, Dick & Harriet, and Dick has Danni & Laura working for them and Laura employs John and Jess but Danni employs Hilary and Gordon, whilst Harriet employs 3 people called person1, person2 & person3 etc. It might look a bit like this:

    SomerFest
    + Michael
     -+Tori
     -+Dick
      --+Danni
        ---Hilary
        ---Gordon
       --+Laura
        ---John
        ---Jess
     -+Harriet
      --Person1
      --Person2
      --PersonEtc


    The question I am asking is if I get Somerfest from a content picker and have it's node Id and I only want to know the node Id of the first crew node. IE Michael - what is his node ID? 

    If I use umbraco.library:GetXmlNodeById($currentPage/eventPicker)the XML that is returned will include everyone down to "---PersonEtc"

    I've tried various ideas like:

    <xsl:variable name="eventNode" select="umbraco.library:GetXmlNodeById($ $currentPage/eventPicker )"/>
    <
    xsl:copy-of select="$eventNode/child::tegsCrew[@isDoc]"/>

    but I always get everything, and not just the first one, in spite of Michael being the only child of the event that is a tegsCrew node

    The issue seems to be that the child nodes are effectively always part of the selection. How can I get only the nodeId of the first tegsCrew node?

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Jun 27, 2012 @ 22:43
    Chriztian Steinmeier
    1

    Hi John,

    As you correctly note, an XPath like $eventNode/tegsCrew[@isDoc] will select all matching children - fortunately, you just need to add a position predicate to get the one you want:

    <xsl:variable name="firstCrewMember" select="$eventNode/tegsCrew[@isDoc][1]" />

    /Chriztian

  • Lee Kelleher 4026 posts 15836 karma points MVP 13x admin c-trib
    Jun 27, 2012 @ 22:44
    Lee Kelleher
    1

    Hi John,

    You're going to kick yourself... you were so close!  Try adding "[1]" to the XPath.

    <xsl:copy-of select="$eventNode/tegsCrew[@isDoc][1]"/>

    Although there is some confusion to why it's "1" and not "0" ... but that's the C# dev in me! ;-)

    Cheers, Lee.

  • John C Scott 473 posts 1183 karma points
    Jun 27, 2012 @ 22:45
    John C Scott
    0

    Hmmmm... i thought I tried the [1] first of all, I'll try it again now
    thank you chaps :) 

    it seemed like although I was only getting the first result that result included all it's children because they were part of it - but I may be going a bit mad there.

  • John C Scott 473 posts 1183 karma points
    Jun 27, 2012 @ 22:47
    John C Scott
    0

    WRT

    >select all matching children

    only Michael is a child, the rest are descendents or children of Michael and not chidlren of the event

    i know i should have got the hang of this by now but i am a bit confused as ever

  • Lee Kelleher 4026 posts 15836 karma points MVP 13x admin c-trib
    Jun 27, 2012 @ 22:47
    Lee Kelleher
    0

    Curses to you Chriztian ... beat me to the punch! If I wasn't trying to make some comment about C# indexes.

  • John C Scott 473 posts 1183 karma points
    Jun 27, 2012 @ 22:52
    John C Scott
    0

    blessings on you both 

    BUT

    the strange thing is

    $eventNode/child::tegsCrew[@isDoc][1]

    does still give me all the children

    as does 

    $eventNode/child::tegsCrew[@isDoc][position()=1]

    it seems as if the variable returned actually includes the children as part of the selected node

    that sounds a bit daft but i am not sure what i should be doing here

    i was a bit surprised when that didn't work first time...

     

    also I may really be showing my ignorance now but

    $eventNode/child::tegsCrew[@isDoc][1]/@Id

    returned aboslutely nothing

  • Lee Kelleher 4026 posts 15836 karma points MVP 13x admin c-trib
    Jun 27, 2012 @ 22:55
    Lee Kelleher
    0

    Quick check: @Id needs to be lowercase.

  • Lee Kelleher 4026 posts 15836 karma points MVP 13x admin c-trib
    Jun 27, 2012 @ 22:59
    Lee Kelleher
    1

    It does make sense...  you want the node for Michael, which is the only child node (below the event node).

    So the XPath: "$eventNode/child::tegsCrew[@isDoc][1]" will give you Michael.

    But Michael's node contains all his staff (child nodes) ... so when you view a <xsl:copy-of> you'll see them all.

    Hope this makes sense?

    Cheers, Lee.

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Jun 27, 2012 @ 23:02
    Chriztian Steinmeier
    0

    Hi John,

    Yes - when you do a copy-of you'll get a deep copy of that node, and all of it's children. But that doesn't really matter because that's almost never what you want. You want access to some property on that node, and setting a variable to $eventNode/tegsCrew[1] does not cost you anything - afterwards, you can access all the properties of the node, e.g:

    <xsl:variable name="firstCrewMember" select="$eventNode/tegsCrew[1]" />
    
    ID: <xsl:value-of select="$firstCrewMember/@id" />
    Name: <xsl:value-of select="$firstCrewMember/@nodeName" />
    etc.

    - But of course you knew all that - I'm guessing your mind played a trick on you when seeing all the descendants in the copy-of ...

    After all - it's the exact same mechanism that makes it possible for Umbraco to hand us $currentPage which is the *entire* XML structure, but with a neat handle at the page we need at that specific point.

    Regarding the zero- or one-based thing, I look at it this way, remembering my assembler skillzz from the good old ZX Spectrum days: In C# and countless other languages, you use "0-based indexing" in the vein that when you access an array, the array is a pointer to the first item and then you specify the offset for the item you want, so to get the first you obviously offset by zero.

    The positional predicate in XPath is a shorthand for writing [position() = 1] so you're asking for the specific thing at position one, not the one at offset zero... anyways, it makes much better sense to me when dealing with sets. 

    /Chriztian

  • John C Scott 473 posts 1183 karma points
    Jun 27, 2012 @ 23:14
    John C Scott
    0

    he heee :)  i have happy memories of Zilog Z80 assembler :) was my second language - happy days of beeps and 8 colours :)
    i started on 1K in a ZX80 (nailed to the wall above my desk now) ~ where of course 1K was a vast exageration of the RAM available :D
    my friend Ben has recently been posting some great screenshots from the books like this one http://robotduck.com/tinygrab/hG99d.jpg

    yes zero offset v. position one makes a lot of sense - i'll remember this

    however this is still foxing me ~ if I write

    <xsl:copy-of select="$eventNode/child::tegsCrew[@isDoc][1]/@id"/>

     I just get an error processing XSLT file - no idea why :(

     

  • Chriztian Steinmeier 2800 posts 8790 karma points MVP 8x admin c-trib
    Jun 27, 2012 @ 23:23
    Chriztian Steinmeier
    0

    Hi John,

    That, my friend, is because you can't copy an attribute to the "result tree" at the point you're doing it - you can only do that immediately after you've opened an element, e.g.:

    <div>
       <xsl:copy-of select="@id" /><!-- OK here -->
    </div>
    
    <div>
       Bla bla tetxt <!-- Content inside tag has been started, so ... -->
       <xsl:copy-of select="@id" /><!-- Will fail -->
    </div>

    Use value-of for output and XML Dump for viewing the XML (seriously - soo good :-)

    /Chriztian 

  • John C Scott 473 posts 1183 karma points
    Jun 28, 2012 @ 00:09
    John C Scott
    0

    YAYY it works :)

    <xsl:value-of select="$eventNode/child::tegsCrew[@isDoc][1]/@id"/>

    so the main mistake it seems i made was caring what i saw in copy-of instead of just getting on with the project and getting the value-of

    thank you ever so much 

    again :)

Please Sign in or register to post replies

Write your reply to:

Draft