XPath or XSL Transform Help

C

Candle

I am new to XML Programming and I am hoping someone can help me out
with this.

Assuming I have the following XML:

<root>
<E C="P_E1" O="E1" Y='True'>
<A C="P_E1A1" V="7" Y='True'/>
<A C="P_E1A2" V="8" />
</E>
<E C="P_E2" O="E1">
<A C="P_E1A1" V="7" />
<A C="P_E1A2" V="8" />
</E>
<E C="P_E3" O="3" Y='True'>
<A C="P_E3A1" V="15" Y='True'/>
<E C="P_E3E1" O="E1" Y='True'>
<A C="P_E3E1A1" V="15" Y='True'/>
<A C="P_E3E1A2" V="16" />
<A C="P_E3E1A3" V="17" />
<A C="P_E3E1A4" V="18" />
<E C="P_E3E1E1" O="E1" Y='True'>
<A C="P_E3E1E1A1" V="15" Y='True'/>
</E>
</E>
</E>
<E C="P_E4" O="4" >
<A C="P_E4A1" V="19" />
<A C="P_E4A2" V="20" />
<E C="P_E4E1" O="E1" Y='True'>
<A C="P_E4E1A1" V="15" Y='True'/>
</E>
</E>
</root>

Basically, I want an xPath that will select all of the top most E
elements where Y='True'.
When I write top most, I mean only the followng:
- the parent, not children
- single node, if there are no children

So, for the example above, the following nodes would be selected:
- <E C="P_E1" O="E1" Y='True'>
- <E C="P_E3" O="3" Y='True'>
- <E C="P_E4E1" O="E1" Y='True'>

I assume this can be done; I just cannot get the syntax down.

Here is what I have so far: //E [@Y='True']. However, this selects all
of the nodes including the children.

If this helps, the Y attribute will either be equal to True on not
exist. As shown in the example above.

After those nodes are selected, I need to transform the nodes using
XSLT. I am mentioning this just in case the xPath cannot be written
and XSLT needs to be used to select the nodes. Once the nodes are
selected, I think I can take it from there.

Thanks for your help.

Regards,

R
 
J

Joseph Kesselman

Candle said:
Basically, I want an xPath that will select all of the top most E
elements where Y='True'.

Your only difficulty here is making "top most" something that's
sufficiently explicit that you can express it in XSLT.

One way to say this: You want all E elements whose Y attribute is
"True", but whose parent's Y attribute is either absent or not "True".

//E[@Y="True" and not(../@Y="True")]

It's probably more efficient to rephrase this as: You want all E
elements whose Y attribute is "True", that are children of an element
whose Y attribute is either absent or not "True".

//*[not(@Y="True")]/E[@Y="True"]

If you know the parent is always going to be an E, it's probably even
more efficient to say:

//E[not(@Y="True")]/E[@Y="True"]

This is assuming that once Y becomes True, it is True for all descendant
E's below that point ... otherwise, this simple parent/child test
applied to all available E's won't work, and you'll need a more explicit
description of what "top most" means.
 
C

Candle

Joseph,

Worked like a charm.

Thx,

R

Joseph said:
Candle said:
Basically, I want an xPath that will select all of the top most E
elements where Y='True'.

Your only difficulty here is making "top most" something that's
sufficiently explicit that you can express it in XSLT.

One way to say this: You want all E elements whose Y attribute is
"True", but whose parent's Y attribute is either absent or not "True".

//E[@Y="True" and not(../@Y="True")]

It's probably more efficient to rephrase this as: You want all E
elements whose Y attribute is "True", that are children of an element
whose Y attribute is either absent or not "True".

//*[not(@Y="True")]/E[@Y="True"]

If you know the parent is always going to be an E, it's probably even
more efficient to say:

//E[not(@Y="True")]/E[@Y="True"]

This is assuming that once Y becomes True, it is True for all descendant
E's below that point ... otherwise, this simple parent/child test
applied to all available E's won't work, and you'll need a more explicit
description of what "top most" means.
 

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,773
Messages
2,569,594
Members
45,117
Latest member
Matilda564
Top