Win a copy of The Little Book of Impediments (e-book only) this week in the Agile and Other Processes forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

A doubt about Xpath expression

 
Niraj Sheth
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
friends,
I am confused about the output when I apply following stylesheet for given xml. I just want to print out content of first and last CCC elements.
Here is the XML file
<?xml version="1.0" ?>
<AAA>
<BBB>
<CCC id="c1">CCC1</CCC>
</BBB>
<BBB>
<CCC id="c2">CCC2</CCC>
</BBB>
<BBB>
<CCC id="c3">CCC3</CCC>
</BBB>
</AAA>
Here is the Stylesheet.
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl utput method="xml"/>
<xsl:template match="/">
first-last : <xsl:value-of select="//CCC[1]"/> - <xsl:value-of select="//CCC[last()]"/>
</xsl:template>
</xsl:stylesheet>

Here is the output ( I have used Xalan processor )
<?xml version="1.0" encoding="UTF-8"?>
first-last : CCC1 - CCC1

what I expected was

<?xml version="1.0" encoding="UTF-8"?>
first-last : CCC1 - CCC3
I would appreciate if anybody can clear my doubts about this. I thought "//CCC[1]" would return first CCC element in the document and "//CCC[last()]' would select the last CCC element in the document.
 
Suresh Teeparti
Greenhorn
Posts: 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Neeraj,
The xpath you have written is behaving exactly the way it is supposed to be.
"//CCC[last()]" returns all the last 'CCC' nodes under its parent ('BBB') hence the xpath returns multiple nodes namely (CCC1, CCC2, CCC3) because u have used value-of select the first one (CCC1) gets printed.
If you want to print the last CCC node of the document and If the node CCC is always under BBB then u can modify your xPath as "//BBB[position()=last()]/CCC[position()=last()]"
Hope I've made myself clear
Get back in case u need more inputs .
Thanks
-Suresh T
 
Niraj Sheth
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks Suresh,
That make sense. I really missed this concept. Trying some examples always helps. I always like to put things in words. Please correct me if I am wrong.
XPath functions like position, last, size, current always applies to the current context ( and not to the node-set returned by the XPath expression ). So last() in "//CCC[last()]" doesn't apply to the node-set containing all CCC elements returned by //CCC but it applies to the current context for the every CCC element returned by the node-set. So this expression selects all CCC elements which are last in thier own cotext.
 
Roseanne Zhang
Ranch Hand
Posts: 1953
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A better solution, it will work without concern of its parent. The parenthesis makes the magic.
 
Roseanne Zhang
Ranch Hand
Posts: 1953
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Niraj Sheth:
XPath functions like position, last, size, current always applies to the current context ( and not to the node-set returned by the XPath expression ). So last() in "//CCC[last()]" doesn't apply to the node-set containing all CCC elements returned by //CCC but it applies to the current context for the every CCC element returned by the node-set. So this expression selects all CCC elements which are last in thier own cotext.

No your explanation is not correct. //CCC[1]
is selecting all first CCC elements. (//CCC)[1] is selecting all CCC elements, then take the first from the result node-set.
Obviously, what you want is the second.
 
Jayadev Pulaparty
Ranch Hand
Posts: 662
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can you give little more details as to how the paranthesis is making the difference here or give us a link wherein we can find the relevant info.
Thanks.
 
Roseanne Zhang
Ranch Hand
Posts: 1953
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Another thing to be noted:
When the XPath returns a node-set with more than one nodes, the xsl:value-of will only display the first node from the result node-set. That is why you got the CCC1 twice. You actually got three nodes from your both XPath.
 
Jayadev Pulaparty
Ranch Hand
Posts: 662
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also, how should we look at the square brackets. Can i think of them as the "predicate" for selecting a node and still arrive at the same conclusion?? I'm a little confused here.
 
Jayadev Pulaparty
Ranch Hand
Posts: 662
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I guess i got it. It would definitely be a predicate for selecting the node and hence we should look at it clearly as a complete node-set and hence the paranthesis. Thanks for the info. Please correct me if i'm wrong.
 
Jayadev Pulaparty
Ranch Hand
Posts: 662
 
Niraj Sheth
Greenhorn
Posts: 16
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Roseanne and Jaydev
Thanks for your clarification. I feel a lot more comfortable now. I still need to play with some examples to clear any doubts.
 
Dan Drillich
Ranch Hand
Posts: 1183
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Can someone please tell me what's the difference between the predicates [@id='c3'] and [position()=3]?
As in -
count-@c3 : <xsl:value-of select="count(//CCC)"/> - <xsl:value-of select="//CCC[@id='c3']"/>
Thanks,
Dan
 
Jayadev Pulaparty
Ranch Hand
Posts: 662
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This problem is something analogous to operator precedence kind of stuff. Even in C language, when you deal with double, triple, etc. pointers, we need to be very careful about the precedence - something like shown here (*ptr)[1] or *ptr[1]. Whenever we are not very sure about how the precedence works, better be very clear with paranthesis and this principle applies everywhere. BTW, one of the good tutorials for you to practice XLST is at www.zvon.org and also the 50XSLT tips given on this forum sometime back is also good.
 
Dan Drillich
Ranch Hand
Posts: 1183
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The specification at http://www.w3.org/TR/xpath says -

NOTE: The location path //para[1] does not mean the same as the location path /descendant: :p ara[1]. The latter selects the first descendant para element; the former selects all descendant para elements that are the first para children of their parents.

Therefore, in our example, /descendant::CCC[position()=3] will also do the job.
Cheers,
Dan
[ December 04, 2002: Message edited by: Dan Drillich ]
 
Jayadev Pulaparty
Ranch Hand
Posts: 662
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dan,
The mystery part to me still is as to why "//CCC[@id='c3']" is looking at all the nodes for the attribute value match, even without the paranthesis.
 
Dan Drillich
Ranch Hand
Posts: 1183
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jayadev,
For some more fun, please look at -

and -

and its variations.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic