XPathNavigator can't find nodes despite XmlNamespaceManager

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!

Jon Skeet
people
quotationmark

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();

people

See more on this question at Stackoverflow