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:
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"
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:
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.
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:
- 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.
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
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 :-)
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:
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?
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:
/Chriztian
Hi John,
You're going to kick yourself... you were so close! Try adding "[1]" to the XPath.
Although there is some confusion to why it's "1" and not "0" ... but that's the C# dev in me! ;-)
Cheers, Lee.
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.
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
Curses to you Chriztian ... beat me to the punch! If I wasn't trying to make some comment about C# indexes.
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
Quick check: @Id needs to be lowercase.
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.
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:
- 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
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 :(
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.:
Use value-of for output and XML Dump for viewing the XML (seriously - soo good :-)
/Chriztian
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 :)
is working on a reply...