sazr
sazr

Reputation: 25928

XPath String that grabs an element with a specific id value

I am trying to create an XPath query/string that grabs a specific element from a XML document. I am attempting to grab the element with the id=38 but my code always returns nothing for some reason.

If you look at my code & the organisation of my XML file can you tell me what XPath I need to grab the element with the id=38?

My code is:

XmlDocument xdoc = new XmlDocument();
xdoc.Load(getProductURL());
XmlNode node = xdoc.DocumentElement.SelectSingleNode("id('38')");

// node always is null for some reason?

The way the xml is organised is like so:

<courseg>
    <group isempty="False" isbranch="true" id="1" name="abc">
        <group isempty="False" isbranch="true" id="38" name="def"></group>
    </group>
</courseg>

Upvotes: 14

Views: 20946

Answers (4)

Michael Kay
Michael Kay

Reputation: 163342

The function id('P38') would select an element with an ID value of P38. But this doesn't just mean "an attribute named 'id'". It means an attribute declared in the DTD or schema as being of type ID. You haven't shown a DTD or schema, and I suspect you don't have one. If you did, and if it declared the id attribute as being of type ID, then your document would be invalid, because an ID value cannot be all-numeric (for legacy SGML reasons, it has to take the form of a name).

In practice the id() function is probably best avoided unless you have severe performance requirements. It's too fragile - it only works when you are validating the source document against a schema or DTD. In XSLT, use key() instead. Alternatively, many processors now recognize the attribute name xml:id as a 'self declaring' ID value without reference to a schema or DTD: use that if your processor supports it.

Upvotes: 5

Pritam Karmakar
Pritam Karmakar

Reputation: 2801

When you mention

xdoc.DocumentElement.SelectSingleNode("id('38')"

you are asking xmldocument to search for a child node inside root node whose name is 'id'. But ideally 'id' is an attribute and not a xmlnode.

So you have to use //group[@id = '38'] to get all child node having name 'group' and attribute 'id' with a value of 38

Upvotes: -1

Kirill Polishchuk
Kirill Polishchuk

Reputation: 56172

Use this XPath query:

//*[@id = 38]

It selects every node with id attribute equals to 38. If you have to be more specific, i.e. select group with id attribute equals to 38, use this one:

//group[@id = 38]

Upvotes: 4

Petar Ivanov
Petar Ivanov

Reputation: 93030

The XPath you need is

//*[@id='38']

Here is the example with XDocument:

        XDocument xdoc = XDocument.Parse(@"
<courseg>
    <group isempty=""False"" isbranch=""true"" id=""1"" name=""abc"">
        <group isempty=""False"" isbranch=""true"" id=""38"" name=""def""></group>
    </group>
</courseg>");
        XElement node = xdoc.Root.XPathSelectElement("//*[@id='38']");
        Console.WriteLine(node);

Upvotes: 24

Related Questions