I hate to ask yet another XPath/XmlNamespaceManager question, but I can't seem to figure this out.
I used XpathVisualizer tool which can correctly detect the node using XPath "//FuelGradeMovement". It recognized the namespaces and evaluated the XPath just like that.
I only want to check if the node "FuelGradeMovement" exists. Easy enough. But no, doesn't work.
Clearly the node I am xpath'ing doesn't even have a prefix, but if I don't use the namespace manager I get a runtime error, as other nodes in the document do have prefixes.
And with the namespace it just doesn't see the node for some reason.
I am trying to parse this document:
<?xml version="1.0"?>
<NAXML-MovementReport version="3.4" xmlns="http://www.naxml.org/POSBO/Vocabulary/2003-10-16" xmlns:radiant="http://www.radiantsystems.com/NAXML-Extension" xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.naxml.org/POSBO/Vocabulary/2003-10-16 NAXML-PBI34RadiantExtended.xsd">
<TransmissionHeader>....
</TransmissionHeader>
<FuelGradeMovement/>
</NAXML-MovementReport>
using this code:
using ( var fs = file.OpenRead() )
{
var x = new XPathDocument( fs );
var nav = x.CreateNavigator();
var mgr = new XmlNamespaceManager( nav.NameTable );
mgr.AddNamespace( "xsi", "http://www.w3.org/2001/XMLSchema-instance" );
mgr.AddNamespace( "xmime", "http://www.w3.org/2005/05/xmlmime" );
mgr.AddNamespace( "radiant", "http://www.radiantsystems.com/NAXML-Extension" );
mgr.AddNamespace( "ns1", "http://www.naxml.org/POSBO/Vocabulary/2003-10-16" );
var iterator = nav.Select( "//FuelGradeMovement", mgr );
return iterator.Count > 0;
}
I tried so many combinations but I don't see my mistake. Can anyone help?
Thank you!
You're specifiying the namespace manager - but not the namespace. The FuelGradeMovement
element has inherited the "http://www.naxml.org/POSBO/Vocabulary/2003-10-16"
namespace URI from its parent, so I believe you want:
var iterator = nav.Select("//ns1:FuelGradeMovement", mgr);
Just because the element doesn't specify a namespace prefix doesn't mean it's not in a namespace.
Note that unless you really want complicated XPath queries, LINQ to XML makes all of this a lot simpler. For example:
var doc = XDocument.Load(fs);
XNamespace ns = "http://www.naxml.org/POSBO/Vocabulary/2003-10-16";
return doc.Descendants(ns + "FuelGradeMovement").Any();
See more on this question at Stackoverflow