RonaldoCooper
RonaldoCooper

Reputation: 23

.NET XPathNavigator not finding the elements specified in XPath query (but the XPath query works in XMLSpy)

I have the following C# code snippet to use XPath to find errors in a XML file which is being input:

string xml; // the XML is passed as a parameter as the string below
using (Stream messageStream = new MemoryStream(xml))
{
    IXPathNavigable source = new XPathDocument(messageStream);
    XPathNavigator navigator = source.CreateNavigator();
    object evaResult = navigator.Evaluate("boolean(/thinktransferDataSet/ErrorLog)"); // returns false
    XPathNodeIterator iterator = navigator.Select("/thinktransferDataSet/ErrorLog/sKey"); // returns empty  iterator

    // Assert evaResult is true and iterator has elements.  Both assertions fail
}

Here is the text of the XML file:

<?xml version="1.0" standalone="yes"?>
<thinktransferDataSet xmlns="http://tempuri.org/thinktransferDataSet1.xsd">
    <ProcessHeader>
        <sKey>uniqueId</sKey>
        <sApplication>appname</sApplication>
        <sUser>username</sUser>
        <dtProcessDate>Oct  8 2015  9:58AM</dtProcessDate>
        <iProcessId>5132</iProcessId>
        <iTranFailureCount>2</iTranFailureCount>
        <iTranSuccessCount>0</iTranSuccessCount>
    </ProcessHeader>
    <ErrorLog>
         <sKey>uniqueId</sKey>
         <sLevel>ERROR</sLevel>
         <sDescription>Error in table :tablename Row:1 - Column 'comments' exceeds the MaxLength limit.</sDescription>
         <sSource>69</sSource>
         <dtDate>Oct  8 2015  9:59AM</dtDate>
    </ErrorLog>
    <ErrorLog>
         <sKey>uniqueId</sKey>
         <sLevel>ERROR</sLevel>
         <sDescription>Test error description</sDescription>
         <sSource>69</sSource>
         <dtDate>Oct  8 2015  9:59AM</dtDate>
    </ErrorLog>
</thinktransferDataSet>

Errors are indicated by the presence of one or more elements in the XML. However, with the test message below the navigator.Evaluate and navigator.Select elements are simply not finding the elements or ErrorLog/sKey elements even though these XPath strings completely work in XMLSpy. What could be the issue here?

Many thanks!

Upvotes: 2

Views: 588

Answers (3)

SeongTae Jeong
SeongTae Jeong

Reputation: 335

You have to process namespace 'xmlns="http:...xsd"' at your code like this,

XPathExpression xpe = XPathExpression.Compile("boolean(/ns:thinktransferDataSet/ns:ErrorLog)");

XmlNamespaceManager xnm = new XmlNamespaceManager(navigator.NameTable);
xnm.AddNamespace("ns", "http://tempuri.org/thinktransferDataSet1.xsd");

xpe.SetContext(xnm);

object evaResult = navigator.Evaluate(xpe); // will return true as expected

Upvotes: 0

Ales Buzhynsky
Ales Buzhynsky

Reputation: 77

In order to select elements that belong to a namespace, in any XPath expression their names must be prefixed with a prefix that is associated with this namespace. You can read more detailed answer here. According to you code you can change it so to get it working:

    IXPathNavigable source = new XPathDocument(messageStream);
    var xmlNamespaceManager = new XmlNamespaceManager(navigator.NameTable);
    xmlNamespaceManager.AddNamespace("x", "http://tempuri.org/thinktransferDataSet1.xsd");
    object evaResult = navigator.Evaluate("boolean(/x:thinktransferDataSet/x:ErrorLog)", xmlNamespaceManager);
    XPathNodeIterator iterator = navigator.Select("/x:thinktransferDataSet/x:ErrorLog/x:sKey", xmlNamespaceManager);

Upvotes: 4

jdweng
jdweng

Reputation: 34431

Try this

        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);
            List<XElement> errorLogs = doc.Descendants().Where(x => x.Name.LocalName == "ErrorLog").ToList();
            XNamespace ns = errorLogs[0].Name.Namespace;
            var sKeys = errorLogs.Select(x => new {
                sKey = x.Element(ns + "sKey").Value
            }).ToList();
        }

Upvotes: 0

Related Questions