Thread: Last tango in Paris
Brought to you by:
bs_php,
nigelswinson
From: Peter R. <php...@pe...> - 2002-02-20 19:15:58
|
If I have a lot of tango nodes with a place attribute, and I want to find the 5th tango in Paris, according to the Xpath definition, I should be able to do: tango[@place="Paris"][5] similarly, if I want to find the last tango in Paris, I should be able to do: tango[@place="Paris"][last()] However, I've tried numerous variations on this in the usecases testbench and can't get it to work - it either finds nothing or tells me there's an invalid number of brackets. I can find all the tangos in Paris, and the last tango, but not the two together. Is this a bug, something not handled (yet?), or is there some other notation I can use? (ok, I know I can fetch all the tangos in Paris and then use PHP to get the last in the array.) |
From: Nigel S. <nig...@us...> - 2002-02-20 23:58:43
|
> If I have a lot of tango nodes with a place attribute, and I want to find the > 5th tango in Paris, according to the Xpath definition, I should be able to do: > > tango[@place="Paris"][5] > > similarly, if I want to find the last tango in Paris, I should be able to do: > > tango[@place="Paris"][last()] > > However, I've tried numerous variations on this in the usecases testbench and > can't get it to work - it either finds nothing or tells me there's an invalid > number of brackets. I can find all the tangos in Paris, and the last tango, > but not the two together. Is this a bug, something not handled (yet?), or is > there some other notation I can use? (ok, I know I can fetch all the tangos > in Paris and then use PHP to get the last in the array.) I wonder if this is related to the fact that //*[last()] returns multiple nodes instead of one? I tried: //employee[(@gender='m') and (position() = last())] against: company-structure.xml at: http://www.carrubbers.org/scripts/php/xpath/testBench/useCases/index.php And it returns: [0] => /company[1]/department[1]/employee[2] [1] => /company[1]/department[2]/employee[2] [2] => /company[1]/department[4]/employee[2] [3] => /company[1]/department[5]/employee[2] Where: //employee[(@gender='m')] Returns: [0] => /company[1]/department[1]/employee[1] [1] => /company[1]/department[1]/employee[2] [2] => /company[1]/department[2]/employee[1] [3] => /company[1]/department[2]/employee[2] [4] => /company[1]/department[3]/employee[1] [5] => /company[1]/department[4]/employee[1] [6] => /company[1]/department[4]/employee[2] [7] => /company[1]/department[5]/employee[1] [8] => /company[1]/department[5]/employee[2] Is that any use?? Nigel =========================== For the most recent version of Php.XPath, and an archive of this list visit: http://www.sourceforge.net/projects/phpxpath |
From: Dietrich A. <die...@ga...> - 2002-02-21 02:36:07
|
Nigel, is multiple predicates implemented? ie: //node-test[myPredicate1][myPredicate2] if it's not, it would explain the "too many brackets" error. Peter, assuming that you actually have a tango element that contains the attribute "place" with a value of "paris" *and* all the "paris" nodes contain the same immediate parent, then the original xpath expression is correct and should only return 1 node: //tango[@place="paris"][last()] But if you have "paris" nodes that have *different* parents, then you may receive multiple nodes, as each my be the last child of the respective context node. From the spec, section 2.5 Abbreviated Syntax: "para[last()] selects the last para child of the context node" - d. > -----Original Message----- > From: php...@li... > [mailto:php...@li...]On Behalf Of Nigel > Swinson > Sent: Wednesday, February 20, 2002 3:59 PM > To: php...@li... > Subject: Re: Last tango in Paris > > > > If I have a lot of tango nodes with a place attribute, and I want to find > the > > 5th tango in Paris, according to the Xpath definition, I should be able to > do: > > > > tango[@place="Paris"][5] > > > > similarly, if I want to find the last tango in Paris, I should be able to > do: > > > > tango[@place="Paris"][last()] > > > > However, I've tried numerous variations on this in the usecases testbench > and > > can't get it to work - it either finds nothing or tells me there's an > invalid > > number of brackets. I can find all the tangos in Paris, and the last > tango, > > but not the two together. Is this a bug, something not handled (yet?), or > is > > there some other notation I can use? (ok, I know I can fetch all the > tangos > > in Paris and then use PHP to get the last in the array.) > > I wonder if this is related to the fact that //*[last()] returns multiple > nodes instead of one? > > I tried: > > //employee[(@gender='m') and (position() = last())] > > against: > > company-structure.xml > > at: > > http://www.carrubbers.org/scripts/php/xpath/testBench/useCases/index.php > > And it returns: > > [0] => /company[1]/department[1]/employee[2] > [1] => /company[1]/department[2]/employee[2] > [2] => /company[1]/department[4]/employee[2] > [3] => /company[1]/department[5]/employee[2] > > Where: > > //employee[(@gender='m')] > > Returns: > > [0] => /company[1]/department[1]/employee[1] > [1] => /company[1]/department[1]/employee[2] > [2] => /company[1]/department[2]/employee[1] > [3] => /company[1]/department[2]/employee[2] > [4] => /company[1]/department[3]/employee[1] > [5] => /company[1]/department[4]/employee[1] > [6] => /company[1]/department[4]/employee[2] > [7] => /company[1]/department[5]/employee[1] > [8] => /company[1]/department[5]/employee[2] > > Is that any use?? > > Nigel > > =========================== > For the most recent version of Php.XPath, and an archive of this list visit: > http://www.sourceforge.net/projects/phpxpath > > > _______________________________________________ > Phpxpath-users mailing list > Php...@li... > https://lists.sourceforge.net/lists/listinfo/phpxpath-users > |
From: Peter R. <php...@pe...> - 2002-02-21 14:01:18
|
On Thursday 21 Feb 2002 5:44 am, Dietrich Ayala wrote: > But if you have "paris" nodes that have *different* parents, then you may > receive multiple nodes, as each my be the last child of the respective > context node. yes, unless I use the context parameter. Either way it should return something and not fall over with an error. |
From: Nigel S. <nig...@us...> - 2002-05-30 23:56:00
|
Peter brought this bug up a while back, but we'd forgotten about it. It has been fixed now. The brief story is that double predicates like /*[last()][@Attr='X'] will now work. If you want more background then you can read on some of Peter and my discussion from this evening... I think it is unlikely that this bug affects you. I think most XPath users only use one [] not two or more [][], but thought I should post to the list just in case it does. :o) Nigel > On Thursday 30 May 2002 20:41, Nigel Swinson wrote: > > > > > Also, it looks like the double predicate problem (my 'last tango > > > in Paris' example) is still outstanding - is that correct? > > > > I had to go and research this but I what I found was going to > > http://www.zvon.org:9001/saxon/cgi-bin/XLab/XML/extras.html?stylesh > >eetFile=X SLT/xpath.xslt (Link doesn't seem to be working right just > > now) that //*[last()] could return more than one node, so it seemed > > that we were implementing last() right. > > > > There does however seem to be a second issue todo with > > /nodetest[][] double predicates, which DOES NOT seem to be working. > > I don't know if it's meant to though. Is it? If it is then it > > seems we still have a bug... > > > > Can you confirm? > > yes, these are 2 two different things. The problem is not with last > but with >1 predicates. Look at say the company structure xml in the > useCases testbench. If you do //employee[last()] it will fetch the > last employee node in each parent (dept), 5 of them in this case, > which is correct. If you do //employee[@gender='m'], it will fetch > all the male employees. But if you try and combine the 2, i.e. a > 2-stage process: fetch the male employees and then give me the last > one //employee[@gender='m'][last()] it brings an error that it can't > find a gender function. > The example in the xpath spec is para[@type="warning"][5] > In my tango example, you can fetch all the tangos in Paris, and all > the last tangos, but not the two together. > > These positional ones are not too difficult to work around, as you can > simply read all the first predicate into an array and then use php to > fish out the one you want, but at least in principle, you can have > any predicate and any number of predicates, tho in practice I doubt > whether anyone would have much use for this. > > I don't think this is a bug btw, I don't think it was ever coded :-) > |
From: Nigel S. <nig...@us...> - 2002-06-18 02:26:06
|
> > Whilst testing this, I came across another, um, feature. If you > > have 2 exports one after the other, for example > > ... > > print $xml->exportAsXml(); > > print $xml->exportAsXml(); > > ... > > the first one will have the header, the second and subsequent > > will not. I take it this is a bug and not intentional? Seems to > > have something to do with the node index, though putting > > reindexNodeTree() between the 2 exports had no effect. Turned out to be an obscure but todo with references. Any call to export() would blank over the xmlHeader (or possibly some other string). I'm unconvinced that this was our bug rather than a PHP bug, but we could code round it so we have. Nigel |
From: Peter R. <php...@pe...> - 2002-02-21 14:01:18
|
On Wednesday 20 Feb 2002 11:58 pm, Nigel Swinson wrote: > > I tried: > > //employee[(@gender='m') and (position() = last())] > > against: > > company-structure.xml This is not the same thing. This is the last employee in each parent node if male (or in my example the last of each tango which is in Paris, i.e. all tangos in Paris). What I want is the last instance of all male employees, i.e. //employee[@gender='m'][last()] should find a1010 and gender = 'f' should find a1006. Incidentally, if I try //employee[(@gender='m') and (last())] I get a different answer to your example. What is this doing? 'Position() = last()' and 'last()' should surely be identical. |
From: Nigel S. <nig...@us...> - 2002-02-22 00:10:08
|
Yeah I'm pretty sure that there is a bug in the predicate parsing, but = am not completely sure what is wrong which kinda makes it hard to fix... If you can mail in xml files, with XPath and nodes that should be = selected by the op, then that would be helpful. I've got a couple of = tests that fail, but I haven't had the time to definatively work out if = Php.XPath definately is doing the wrong thing... Sadly I don't see this getting fixed any time soon, the next two months = are very busy for me at the moment, can't speak for Sam and Dan, and = we're fairly deep into V3 at the moment... 4.3 Test xQuery =3D '//*[last()]' =20 <AAA> <BBB/> <BBB/> <BBB/> <BBB/> </AAA> <AAA> <BBB/> <BBB/> <BBB/> <BBB/> </AAA> =20 Recived Expected=20 /AAA[1] /AAA[1]/BBB[4]=20 /AAA[1]/BBB[4] - missing -=20 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D For the most recent version of Php.XPath, and an archive of this list = visit: http://www.sourceforge.net/projects/phpxpath |
From: Nigel S. <nig...@us...> - 2002-07-12 01:48:19
|
(Really old thread alert...) > This is not the same thing. This is the last employee in each parent node if > male (or in my example the last of each tango which is in Paris, i.e. all > tangos in Paris). What I want is the last instance of all male employees, > i.e. > > //employee[@gender='m'][last()] > > should find a1010 and gender = 'f' should find a1006. > > Incidentally, if I try > > //employee[(@gender='m') and (last())] > > I get a different answer to your example. What is this doing? 'Position() = > last()' and 'last()' should surely be identical. //employee[(@gender='m') and (last())] And //employee[(@gender='m') and (position() = last())] Are NOT the same. Because of the "and" operator. what happens is that last() returns a number. The "and" takes two operands that need to be bools, so it has to convert the number from last() into a bool. If you think about it, last() always returns a non zero number, which always converts to TRUE. So for example I got confused by a test that I had that was //*[1 and last()] and was surprised to see that this returned different results to //*[1 and (position() = last())]. //*[1 and last()] actually matched EVERY node in the document. This is because: http://www.w3.org/TR/xpath#section-Node-Set-Functions "The last function returns a number equal to the context size from the expression evaluation context.The last function returns a number equal to the context size from the expression evaluation context." So last returns a non zero number, because context size >= 1. When you convert a non zero number to a bool, you get TRUE. So basically I was doing: //*[1 and TRUE]. So now it's not really surprising that it returned all the nodes. On the other hand, //*[1 and (position() = last())] must now evaluate the "position() = last()" as a bool, which only returns TRUE for the last node in the context. And hence //*[1 and (position() = last())] is the same as //*[(position() = last())] is the same as //*[last()], but is not the same as //*[1 and last()]. Seems a bit bizzare....but means we have less bugs than we'd thought :o) Nigel |
From: Peter R. <php...@pe...> - 2002-07-12 09:38:23
|
On Friday 12 Jul 2002 02:44, Nigel Swinson wrote: > > //employee[(@gender='m') and (last())] > > And > > //employee[(@gender='m') and (position() = last())] > > Are NOT the same. Because of the "and" operator. <snip snip snip> er, yes. Yes, I think you are right. On first glance, xpath syntax is very simple, but there are a lot of pits to fall into :-( |
From: Nigel S. <nig...@us...> - 2002-07-14 01:20:09
|
> On first glance, xpath syntax is very simple, but there are a lot of > pits to fall into :-( Yeah I'm finding loads of them today. I thought XPath was really very very simple, but if you go past the simple queries, it seems to get a little wierd to get just right. Php.XPath currently doesn't cope with a lot of this very well so I'm having a good hack at the moment to bring it up to speed. To my horror I found that a query like this doesn't even work: //*[DDD] :o/ The good news is that it's all slotting together in a much cleaner way now, and the class should be much better because of it. The core XPath code is to a certain degree unchanged from the very original phpxml code that Php.XPath came from. That's all changing now... Nigel |