XPath Relational Query

M

Michael

To all,

I am trying to query an XML document of the following structure.

<ROOT>
<A>
<B id="1"/>
<B id="2"/>
<B id="3"/>
</A>
<A>
<C id="1"/>
<C id="2"/>
<C id="5"/>
<C id="6"/>
</A>
</ROOT>

I want to select all <C> nodes that do not have a <B> element
associated (by id). In other words, what i am looking for is <C
id="5"/> and <C id="6"/>. I realize XPath was not designed to perform
such queries but is there any way to accomplish this?

What I have in mind is something like this:

//C[count(//B[@id = @id]) = 0]

The first "@id" is referencing the "id" attribute of the <B> element. I
want the second "@id" to reference the "id" attribute of the <C>
element. I can't think of any way to do this with axis since they only
allow me to choose nodes relative to the current node which is B.

Thanks,
Michael B.
 
M

mukul_gandhi

Please try this XSL ..

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:eek:utput method="xml" encoding="UTF-8" indent="yes" />

<xsl:template match="/ROOT">
<result>
<xsl:for-each select=".//C">
<xsl:if test="not(@id = preceding::B/@id)">
<xsl:copy-of select="." />
</xsl:if>
</xsl:for-each>
</result>
</xsl:template>

</xsl:stylesheet>

Regards,
Mukul
 
M

Michael

Thanks Mukul,

I cannot use XSL. I am actually using an XmlDocument object as the
internal data structure for a windows .net application, I need to pick
nodes using XPath only. My other option is to write code to perform
this logic, but i was looking for a way to do this with XPath alone.

Thank you for your help.

Regards,
Michael B.
 
M

mukul_gandhi

The XslTransform class of .NET framework allows to do XSLT (1.0)
transformation .. I guess it should help ..

Regards,
Mukul
 
D

David Carlisle

Michael said:
To all,

I am trying to query an XML document of the following structure.

<ROOT>
<A>
<B id="1"/>
<B id="2"/>
<B id="3"/>
</A>
<A>
<C id="1"/>
<C id="2"/>
<C id="5"/>
<C id="6"/>
</A>
</ROOT>

I want to select all <C> nodes that do not have a <B> element
associated (by id). In other words, what i am looking for is <C
id="5"/> and <C id="6"/>. I realize XPath was not designed to perform
such queries but is there any way to accomplish this?

What I have in mind is something like this:

//C[count(//B[@id = @id]) = 0]

The first "@id" is referencing the "id" attribute of the <B> element. I
want the second "@id" to reference the "id" attribute of the <C>
element. I can't think of any way to do this with axis since they only
allow me to choose nodes relative to the current node which is B.

Thanks,
Michael B.

//C[not(@id=//B/@id)]

David
 
M

Michael

Thanks a lot David, that did it.

Do you have any idea how the XPath processor executes this? Does it
execute //B/@id every time the <C> element is found or does it do it
only once and then checks the @id of <C> against that result set.

Thanks,
Michael
 
D

David Carlisle

Michael said:
Thanks a lot David, that did it.

Do you have any idea how the XPath processor executes this? Does it
execute //B/@id every time the <C> element is found or does it do it
only once and then checks the @id of <C> against that result set.

Thanks,
Michael

one or the other:)
it depends on the processor, some do take common expressions out of
loops and probably some don't. I think saxon does, for example.
Most XPath API presumably allow you to declare xpath variables
in which case you could give your processor a hint and stick //B/@id in
a variable and use a variable reference in the predicate, but if your
processor is doing that anyway that will make no difference.

It's not entirely trival for an optimiser to take an expression such as
//B/@id out of a loop as it's not a constant expression, the value of /
and hence the value of //B/@id depends on the document in which the
current current node sits. In this case all the nodes are necessarily in
the same docuument (as they are selected with //C) but in general this
can get tricky.

David
 

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,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top