Question

I've got an XPath expression with a predicate that selects a person's name and ID from within a nested element, using the XPathNavigator.Select method.

This works:

root/all_clients/client/client_name_and_ID[client_ID = 'xxx']

This also works:

root/all_clients/client[client_name_and_ID/client_ID = 'xxx']/client_name_and_ID

When I take the predicate to the next level, it does not work:

root/all_clients[client/client_name_and_ID/client_ID = 'xxx']/client/client_name_and_ID

I do not get any filtering, but the entire set.

Is this due to a limitation inherent within XPath, within ASP.NET, or am I doing something stupid?

What follows is a snippet from the relevant XML file:

<?xml version="1.0" encoding="utf-8"?>

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="file:///n:\Projects\XML\Medical\Example_01.xsd">

<all_clients>

    <client>
        <client_name_and_ID>
            <first_name>Fred</first_name>
            <middle_name>James</middle_name>
            <last_name>Bowman</last_name>
            <client_ID>1</client_ID>
        </client_name_and_ID>
    </client>

    <client>
        <client_name_and_ID>
            <first_name>Mark</first_name>
            <middle_name>David</middle_name>
            <last_name>Colder</last_name>
            <client_ID>2</client_ID>
        </client_name_and_ID>
    </client>

    <client>
        <client_name_and_ID>
            <first_name>Joe</first_name>
            <last_name>Lewis</last_name>
            <client_ID>3</client_ID>
        </client_name_and_ID>
    </client>

    <client>
        <client_name_and_ID>
            <first_name>Sam</first_name>
            <last_name>Plank</last_name>
            <client_ID>4</client_ID>
        </client_name_and_ID>
    </client>
</all_clients>

</root>
Was it helpful?

Solution

The last query is matching an all_clients element that contains any matching client underneath it. It then selects clients under this all_clients without the filter applied, so it selects all of the client elements.

You should save the filter for the end of the XPath. First select down to the type of element you want, and then apply a filter to those elements. Try these XPaths:

<!-- Select client_ID element. -->
root/all_clients/client/client_name_and_ID/client_ID[. = 'xxx']

<!-- Select client_name_and_ID element. -->
root/all_clients/client/client_name_and_ID[client_ID = 'xxx']

<!-- Select client element. -->
root/all_clients/client[client_name_and_ID/client_ID = 'xxx']

OTHER TIPS

That's normal. All client nodes are children of the all_clients node. Therefore it will always qualify to the condition "all elements named all_clients having at least one match of a descendant client/client_name_and_ID/client_ID = 'xxx'" which is what you have coded.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top