XPath predicate problem

Z

Ziphims

I'm having a problem with XPath's predicate. This is the data I'm
dealing right now:


<?xml version="1.0" encoding="UTF-8"?>
<EMPLOYEE ID="2">
<NAME Src="DB">Alan Smith</NAME>
<SEX Src="DB">M</SEX>
<ADDRESSES>
<ADDRESSITEM EMPID="2">
<NAME Src="DB">Apartment</NAME>
<ADDRESS Src="DB">Orchard Rd.</ADDRESS>
<POSTCODE Src="DB">110000</POSTCODE>
</ADDRESSITEM>
</ADDRESSES>
<BIRTHDATE Src="DB">210038400</BIRTHDATE>
<BIRTHLOCATION Src="DB">Jakarta</BIRTHLOCATION>
<RELATEDDATA>
<RELATIONTYPE ID="3">
<NAME Src="DB">Husband</NAME>
<NAME_R Src="DB">Wife</NAME_R>
</RELATIONTYPE>
<RELATIONTYPE ID="4">
<NAME Src="DB">Friend</NAME>
<NAME_R Src="DB"></NAME_R>
</RELATIONTYPE>
<PEOPLE PID="3">
<NAME Src="DB">Elisha Sue</NAME>
<SEX Src="DB">F</SEX>
</PEOPLE>
<PEOPLE PID="10">
<NAME Src="DB">Robert Thompson</NAME>
<SEX Src="DB">M</SEX>
</PEOPLE>
<PEOPLE PID="13">
<NAME Src="DB">Steven Richard</NAME>
<SEX Src="DB">M</SEX>
</PEOPLE>
</RELATEDDATA>
<PHONENUMBERS>
<NUMBERITEM EMPID="2">
<NAME Src="DB">Cellphone (Work)</NAME>
<NUMBER Src="DB">0835 545856425</NUMBER>
</NUMBERITEM>
<NUMBERITEM EMPID="2">
<NAME Src="DB">Home (Fax)</NAME>
<NUMBER Src="DB">5748963</NUMBER>
</NUMBERITEM>
</PHONENUMBERS>
<RELATIONSHIPS>
<RELITEM>
<PEOPLE1 Src="DB">2</PEOPLE1>
<PEOPLE2 Src="DB">3</PEOPLE2>
<RELTYPE Src="DB">3</RELTYPE>
</RELITEM>
<RELITEM>
<PEOPLE1 Src="DB">2</PEOPLE1>
<PEOPLE2 Src="DB">10</PEOPLE2>
<RELTYPE Src="DB">4</RELTYPE>
</RELITEM>
</RELATIONSHIPS>
</EMPLOYEE>



What I'm trying to do is to get the NAME of a PEOPLE element (part of
RELATEDDATA element) having PID of PEOPLE2 element under a RELITEM
element. So far the only thing that is close to what I want is this
expression:

(using RELITEM element as pivot point)
ancestor::*/RELATEDDATA//NAME[parent::pEOPLE/@PID = //PEOPLE2]/
parent::pEOPLE

But as you can guess, it select two PEOPLE because I'm using "//". The
thing is, I'm parsing this document for a program (using libxml2) and
it evaluate one RELITEM element at a time. So what I want is to use
the currently 'selected' RELITEM and get PEOPLE element based on
PEOPLE2 element (under the currently 'selected' RELITEM) value.

I've set the pivot element in libxml2 to use the currently 'selected'
RELITEM but I'm not getting any result from this expression:

ancestor::*/RELATEDDATA//NAME[parent::pEOPLE/@PID = /PEOPLE2]

All of this led me to a question: Is it possible to use pivot element
in libxml inside a predicate? If yes, how?

I'm open to any suggestion, word of wisdom, advice, link, basically
anything to explain this.
 
T

TOUDIdel

Uzytkownik "Ziphims said:
(using RELITEM element as pivot point)
ancestor::*/RELATEDDATA//NAME[parent::pEOPLE/@PID =
//PEOPLE2]/parent::pEOPLE
ancestor::*/RELATEDDATA//NAME[parent::pEOPLE/@PID = /PEOPLE2]

If RELITEM is your context node why do you use //PEOPLE2 or /PEOPLE2 in test
statement instead of PEOLPE2 (without any slashes) which are child nodes of
your RELITEM context node?
 
P

Pavel Lepin

TOUDIdel said:
Uzytkownik "Ziphims said:
(using RELITEM element as pivot point)
ancestor::*/RELATEDDATA//NAME[parent::pEOPLE/@PID =
//PEOPLE2]/parent::pEOPLE
ancestor::*/RELATEDDATA//NAME[parent::pEOPLE/@PID =
/PEOPLE2]

If RELITEM is your context node why do you use //PEOPLE2
or /PEOPLE2 in test statement instead of PEOLPE2 (without
any slashes) which are child nodes of your RELITEM context
node?

Because 'PEOPLE2' in that predicate would refer to PEOPLE2
element children of NAME element referred to in this
location step (of which there are none, obviously), and not
to PEOPLE2 children of context node. What the OP tried
doesn't work either, of course. You gotta generate XPath1
expressions on the fly to do that.

Just a friendly observation: the invariably flawed bits of
advice you post on this group produce a somewhat awkward
impression taken together with the domain name of the
website you advertise in your sig. I mean, eh, guru?..
Ro-oi-ight...
 
J

Joseph Kesselman

Build it up in stages, as with any other programming languages
>NAME of a PEOPLE element (part of
> RELATEDDATA element) having the
>PID of PEOPLE2 element under a RELITEM
> element (using RELITEM element as pivot point)

Find the PEOPLE elements. More explicit paths are faster so...
/EMPLOYEE/RELATEDDATA/PEOPLE

Add a predicate to select the one which has the desired PID.
The PEOPLE2 element doesn't carry a PID attribute, so I'm assuming its
value is intended to be the PID. I'm also assuming that by "pivot point"
you mean "current element". If so, this is simply the value of the
PEOPLE2 element.
/EMPLOYEE/RELATEDDATA/PEOPLE[@PID=current()/PEOPLE2]
The trick here is the use of current(), which says we want the PEOPLE2
child of the current node, NOT of the node we're applying the predicate to.

Now get the NAME child of that selected entry:
/EMPLOYEE/RELATEDDATA/PEOPLE[@PID=current()/PEOPLE2]/NAME












So far the only thing that is close to what I want is this
expression:

(using RELITEM element as pivot point)
ancestor::*/RELATEDDATA//NAME[parent::pEOPLE/@PID = //PEOPLE2]/
parent::pEOPLE

But as you can guess, it select two PEOPLE because I'm using "//". The
thing is, I'm parsing this document for a program (using libxml2) and
it evaluate one RELITEM element at a time. So what I want is to use
the currently 'selected' RELITEM and get PEOPLE element based on
PEOPLE2 element (under the currently 'selected' RELITEM) value.

I've set the pivot element in libxml2 to use the currently 'selected'
RELITEM but I'm not getting any result from this expression:

ancestor::*/RELATEDDATA//NAME[parent::pEOPLE/@PID = /PEOPLE2]

All of this led me to a question: Is it possible to use pivot element
in libxml inside a predicate? If yes, how?

I'm open to any suggestion, word of wisdom, advice, link, basically
anything to explain this.
 
T

TOUDIdel

Uzytkownik "Pavel Lepin said:
Because 'PEOPLE2' in that predicate would refer to PEOPLE2
element children of NAME element referred to in this
location step (of which there are none, obviously), and not
to PEOPLE2 children of context node. What the OP tried
doesn't work either, of course. You gotta generate XPath1
expressions on the fly to do that.

yes you right of course. that statement's writing makes me fool; I always
use current() function to avoid that kind mistakes.
 
J

Joseph Kesselman

Actually, if you're working in pure XPath rather than XSLT, I'm not sure
current() is available. If it isn't, you may need to pass the context
node in as a variable (look at your XPath engine's documentation to see
how to do this) and reference that variable from within the predicate.
 
P

P. Lepin

Joseph said:
Actually, if you're working in pure XPath rather than XSLT, I'm not sure
current() is available.

It isn't, current() is XSLT-specific, and is described in 12.4 of XSLT1.
If it isn't, you may need to pass the context node in as a variable (look
at your XPath engine's documentation to see how to do this) and reference
that variable from within the predicate.

Note that as far as I can tell XPath variable binding is not a part of DOM
API specs, therefore the details vary from parser to parser, although every
XPath processor API's I've seen did it in a reasonably sensible way.

Simply generating the expression on the fly is often the easiest solution,
but, yeah, not one of the Best Practices by any stretch of imagination.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top