Marqueone
Marqueone

Reputation: 1213

How to query an xml element with xpath with an existing namespace

<?xml version="1.0" encoding="utf-8"?> 
<Report p1:schemaLocation="TemplateXXX http://localhost?language=en" Name="TemplateXXX" xmlns:p1="http://www.w3.org/2001/XMLSchema-instance" xmlns="TemplateXXX"> 
   <HEADER attr1="one" attr2="two" /> 
   <Table filename="12345.pdf"> 
      <left> 
         <details> 
            <item/> 
            <item/> 
         </details> 
      </left> 
      <right> 
         <details> 
            <item/> 
            <item/> 
         </details> 
      </right> 
   </Table> 
</Report> 

I'm running into a strange problem when trying to query elements and attributes in an xml document where a namespace is in the xml.

When I try to query the document to get the header element with the following xpath query I consistantly get null results

XDocument root = XDocument.Load(filePath);
var element = root.XPathSelectElement("/Report/HEADER");

This always returns null however the moment I remove the namespace from the document the query returns the exepcted element.

What is it that I'm getting wrong as I'm getting some what frustrated.

edit: updated xml to valid xml

Upvotes: 1

Views: 901

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1499770

I would personally recommend that you didn't do this with XPath, but you can if you really want. Here's a short but complete program which works with your sample XML, after I'd fixed it up (it isn't valid XML at the moment... please try to provide working examples next time):

using System;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;

class Test
{
    static void Main()
    {
        var doc = XDocument.Load("test.xml");
        var manager = new XmlNamespaceManager(new NameTable());
        manager.AddNamespace("foo", "TemplateXXX");

        var query = doc.XPathSelectElement("/foo:Report/foo:HEADER", manager);
        Console.WriteLine(query);
    }
}

In a normal LINQ to XML query you'd just use:

XNamespace ns = "TemplateXXX";
XElement header = doc.RootElement.Element(ns + "HEADER");

No need for a namespace manager etc.

Upvotes: 2

Related Questions