5

The following code works perfect. See XML file below.

XPathDocument xPathDoc = new XPathDocument(@"C:\Authors.xml");
XPathNavigator navigator = xPathDoc.CreateNavigator();
XPathNodeIterator iterator = navigator.Select("/Contacts/Author/FirstName");
iterator.MoveNext();
string firstName = iterator.Current.InnerXml;
Console.WriteLine(firstName);

The value of 'firstName' returns 'Joe' which is perfect. However, when I add this attibute xmlns="http://www.w3.org/1999/xhtml" to the '' tag, so that it looks as follows:

<Author xmlns="http://www.w3.org/1999/xhtml">

then the code does not return the correct value ('Joe') Why then the attribute xmlns="http://www.w3.org/1999/xhtml" affects the code above and what am I missing to return the correct value?

Any help will be greatly appreciated.

Here is the xml file:

<?xml version="1.0" encoding="UTF-8" ?> 
<Contacts>
<Author>
<FirstName>Joe</FirstName>
</Author>
<Teacher>
<FirstName>Larry</FirstName>
</Teacher>

<Painter>
<FirstName>Mary</FirstName>
</Painter>
</Contacts>
John Saunders
  • 160,644
  • 26
  • 247
  • 397
Jay
  • 51
  • 2

2 Answers2

7

xmlns is namespace which is used to avoid conflict between tags of the xml. Scenario, when one app is using xml from multiple sources and same tagname exist in two or more xml files. Since probablity of such ambiguity is high, namespace is used to reduce it.

hungryMind
  • 6,931
  • 4
  • 29
  • 45
5

Your XPath expression is looking for elements "Contacts", "Author" and "FirstName" without namespaces. It looks like the Author element (and any descendant elements which don't have a namespace declaration) do have namespaces, do your XPath expression doesn't match.

To fix it, you'll need to use an XmlNamespaceManager, associate a prefix with the namespace and include that namespace in your XPath expression. Frankly, it gets messy.

Is there any reason you can't use LINQ to XML instead? It makes it much simpler to deal with XML in general and namespaces in particular. I'm happy to come up with a LINQ to XML sample if you're able to use it.

EDIT: Here's some sample LINQ to XML:

XDocument doc = XDocument.Load("authors.xml");
XNamespace ns = "http://www.w3.org/1999/xhtml";
var query = doc.Root
               .Elements(ns + "Author")
               .Elements(ns + "FirstName");
foreach (var element in query)
{
    Console.WriteLine((string) element);
}
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Jon, Thank you very much for answering my question so quickly. I did some reading on XmlNamespaceManager and I can see what you mean by messy. No I am open to use LINQ. It would be great if you can post an example that does the same thing – Jay Jan 18 '11 at 20:48
  • @Jay: Have a look at my edit and see if it's what you're after, or at least a start. – Jon Skeet Jan 18 '11 at 20:52
  • are you sure this line compiles? `XNamespace ns = "http://www.w3.org/1999/xhtml";` you cannot assign a string to a XNamespace object I'd think – user1623521 Jul 29 '20 at 03:01
  • @user1623521: Yes, I'm absolutely positive it compiles. There's an implicit conversion from `string` to `XNamespace`: https://learn.microsoft.com/en-us/dotnet/api/system.xml.linq.xnamespace.op_implicit?view=netcore-3.1 – Jon Skeet Jul 29 '20 at 06:36