carlpett
carlpett

Reputation: 12583

Selecting only direct descendant

I have this structure:

<root>
  <properties>
    <property name="test">
      <value>X</value>
    </property>
  </properties>
  <things>
    <thing>
      <properties>
        <property name="test">
          <value>Y</value>
        </property>
      </properties>
    </thing>
  </things>
</root>

Is there an XPath expression which will select only the test property with value X if run with <root> as root, and only the one with value Y if run with thing as root?

I thought that /properties/property[@name='test'] would require it to be a direct child, but that seems to return nothing. If I remove the slash, I get both property elements (I'm using C#, with XElement root = ...; root.XPathSelectElements(xpathexpression);).

Upvotes: 2

Views: 1886

Answers (3)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243449

I thought that /properties/property[@name='test'] would require it to be a direct child, but that seems to return nothing.

Any XPath expression that starts with a / is an absolute XPath expression -- it is evaluated using the document node (/) as the initial context node.

In your case:

/properties/property[@name='test']

tries to select a top element node named properties (and then its child) and this correctly selects no nodes, because the top element of the XML document has a different name -- root.

You want:

/root/properties/property[@name='test']

The following relative expression is what you want to work in both cases (with initial context node /root and /root/things/thing):

properties/property[@name='test']

Upvotes: 2

Joachim Isaksson
Joachim Isaksson

Reputation: 180917

You're using an absolute path when you should be using a relative one, this works to select only the one right under root;

        string txt = @"<root><properties><property name=""test""><value>X</value></property></properties><things><thing><properties><property name=""test""><value>Y</value></property></properties></thing></things></root>";
        var doc = XDocument.Parse(txt);
        var root = doc.Root;
        var val = root.XPathSelectElements("properties/property[@name='test']");

Upvotes: 1

Rado
Rado

Reputation: 8963

I think you mean Property and not Properties. Try ./properties/property[@name='test']

Upvotes: 3

Related Questions