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>
The xmlns attribute specifies the xml namespace for a document. Note: The xmlns attribute is required in XHTML, invalid in HTML 4.01, and optional in HTML5. Note: The HTML validator at http://w3.org does not complain when the xmlns attribute is missing in an XHTML document.
One of the primary motivations for defining an XML namespace is to avoid naming conflicts when using and re-using multiple vocabularies. XML Schema is used to create a vocabulary for an XML instance, and uses namespaces heavily.
XPath queries are aware of namespaces in an XML document and can use namespace prefixes to qualify element and attribute names. Qualifying element and attribute names with a namespace prefix limits the nodes returned by an XPath query to only those nodes that belong to a specific namespace.
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.
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With