.NET XPathNavigator找不到XPath查询中指定的元素(但XPath查询在XMLSpy中工作)

时间:2015-10-19 17:25:42

标签: c# .net xml xpath

我有以下C#代码段来使用XPath来查找正在输入的XML文件中的错误:

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
}

以下是XML文件的文本:

<?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>

错误由XML中一个或多个元素的存在表示。但是,使用navigator.Evaluate和navigator.Select元素下面的测试消息根本找不到元素或ErrorLog / sKey元素,即使这些XPath字符串完全在XMLSpy中工作。这可能是什么问题?

非常感谢!

3 个答案:

答案 0 :(得分:1)

为了选择属于命名空间的元素,在任何XPath表达式中,它们的名称必须以与此命名空间关联的前缀作为前缀。您可以阅读更详细的答案here。根据您的代码,您可以更改它以使其正常工作:

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

答案 1 :(得分:0)

你必须在你的代码中处理命名空间'xmlns =“http:... xsd”',

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

答案 2 :(得分:0)

试试这个

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