OK, so I've been pulling my hair out all day with this problem in XPATH and C#.
I have the following XML document:
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:g="http://base.google.com/ns/1.0" xmlns:c="http://base.google.com/cns/1.0">
<item id="362">
<title>Family Holiday</title>
<description>a long, wordy description goes here</description>
<g:id xmlns:g="g">FPS</g:id>
<g:latitude xmlns:g="g">42.502260</g:latitude>
<g:longitude xmlns:g="g">1.532850</g:longitude>
</item>
</entry>
I then do the following:
XmlDocument _xmlDocument = new XmlDocument();
_xmlDocument.Load(xmlfile);
XmlNamespaceManager _nameSpaceManager = new XmlNamespaceManager(_xmlDocument.NameTable);
_nameSpaceManager.AddNamespace("RN", "http://www.w3.org/2005/Atom");
_nameSpaceManager.AddNamespace("g", "http://base.google.com/ns/1.0");
_nameSpaceManager.AddNamespace("c", "http://base.google.com/cns/1.0");
XPathNavigator navigator = _xmlDocument.CreateNavigator();
My problem lies with this:
XmlNode nde = _xmlDocument.SelectSingleNode("/RN:entry/RN:item/g:id", _nameSpaceManager);
returns null - not the Id node. However,
XmlNode nde = _xmlDocument.SelectSingleNode("/RN:entry/RN:item/RN:title", _nameSpaceManager);
does return the title node.
Any ideas on what I'm doing wrong would be much appreciated!
Cheers Simon
Your local namespace declarations are overriding the root namespace definitions;
<g:id xmlns:g="g">FPS</g:id>
Is effectively saying the g:id attribute here is coming from the namespace 'g' not the same namespace as g is defined as coming from in your document element.
For example, if I change your XML to:
string xml = @"<entry xmlns=""http://www.w3.org/2005/Atom"" xmlns:g=""http://base.google.com/ns/1.0"" xmlns:c=""http://base.google.com/cns/1.0"">
<item id=""362"">
<title>Family Holiday</title>
<description>a long, wordy description goes here</description>
<g:id xmlns:g=""http://base.google.com/ns/1.0"">FPS</g:id>
<g:latitude xmlns:g=""http://base.google.com/ns/1.0"">42.502260</g:latitude>
<g:longitude xmlns:g=""http://base.google.com/ns/1.0"">1.532850</g:longitude>
</item>
</entry>";
or simply:
string xml = @"<entry xmlns=""http://www.w3.org/2005/Atom"" xmlns:g=""http://base.google.com/ns/1.0"" xmlns:c=""http://base.google.com/cns/1.0"">
<item id=""362"">
<title>Family Holiday</title>
<description>a long, wordy description goes here</description>
<g:id>FPS</g:id>
<g:latitude>42.502260</g:latitude>
<g:longitude>1.532850</g:longitude>
</item>
</entry>";
Your XPath expression works as the local namespace for g now matches the document element namespace declaration of g
If you are stuck with your XML then the only other thing you can do is:
XmlNamespaceManager _nameSpaceManager = new XmlNamespaceManager(_xmlDocument.NameTable);
_nameSpaceManager.AddNamespace("RN", "http://www.w3.org/2005/Atom");
_nameSpaceManager.AddNamespace("g", "g");
_nameSpaceManager.AddNamespace("c", "http://base.google.com/cns/1.0");
Your XPath will now work.
Tested with XmlDocument, .Net Framework version 4.
I would expect the "/RN:entry/RN:item/g:id" XPath expressions to return null - in your XPath the g: namespace alias refers to the namespace "http://base.google.com/ns/1.0", however in your XML document the g: namespace alias has been modified to refer to the namespace "g" on the id, latitude and longitude elements.
Remove the xmlns:g="g" namespace alias definitions on each of these elements and it should work as expected - namespace alias defintions are inherited from parent XML elements and so these aliases are not needed (as well as being incorrect)
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:g="http://base.google.com/ns/1.0">
<item id="362">
<title>Family Holiday</title>
<description>a long, wordy description goes here</description>
<g:id>FPS</g:id>
<g:latitude>42.502260</g:latitude>
<g:longitude>1.532850</g:longitude>
</item>
</entry>
If you want to modify your code to work with the unmodified XML then instead change the definition of the g: namespace declaration in code to match the one in the XML
_nameSpaceManager.AddNamespace("g", "g");
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