C#XML XPath查询不起作用

时间:2016-08-05 06:01:38

标签: c# xml xpath

我不能让我的Xpath查询工作,虽然在纸上它应该是正确的。我甚至试图获得没有属性的单个节点,甚至无法得到这个......

  
    

我做错了什么?

  

Built result trx (cml) format

var trxXml = new XmlDocument();
trxXml.Load(InputTrxFile);
XmlElement root = trxXml.DocumentElement;

var unitTestResult = trxXml.GetElementsByTagName("UnitTestResult");
foreach (XmlElement runinfo in unitTestResult)
{
    // Find failed tests, works fine then... 
     string TestName = runinfo.GetAttribute("testName"); // works fine 
     // Want to find equivalent TestDefinitions/UnitTest
     /* Tried
        TestRun/TestDefinitions/UnitTest[@name='thetest']
        /TestRun/TestDefinitions/UnitTest[@name='thetest']
        TestDefinitions/UnitTest[@name='thetest']
        /TestDefinitions/UnitTest[@name='thetest']
        UnitTest[@name='thetest']
        variations with no attribute test JUST to get a node 
        Example http://www.csharp-examples.net/xml-nodes-by-attribute-value/
      */
    var xpath = string.Format(@"/TestRun/TestDefinitions/UnitTest[@name='{0}']", TestName); 
    XmlNode node = trxXml.SelectSingleNode(xpath);      
    XmlNode node2 = root.SelectSingleNode(xpath);   
    // These all return null

1 个答案:

答案 0 :(得分:1)

任何以/开头的查询都代表绝对路径,即它来自文档的。您的UnitTestResult元素(至少)似乎包含了您的TestRun元素。

要让您的查询考虑当前上下文,您需要引用当前上下文。可以使用.选择此内容。

其次,您的XML元素都有命名空间,这需要构成您查询的一部分。需要将前缀添加到命名空间管理器中,在查询中使用,并将管理器传递给查询方法。

因此,将这些结合起来,定义前缀:

var manager = new XmlNamespaceManager(new NameTable());
manager.AddNamespace("t", "http://microsoft.com/schemas/VisualStudio/TeamTest/2010");

更改您的查询:

./t:TestRun/t:TestDefinitions/t:UnitTest[@name='{0}']

并将命名空间管理器传递给方法:

trxXml.SelectSingleNode(xpath, manager);
但是,XPath和XmlDocument很痛苦。在LINQ to XML中,这一切都会更直接:

var doc = XDocument.Load(InputTrxFile);

var unitTestQuery = 
    from result in doc.Descendants(ns + "UnitTestResult")
    let name = (string)result.Attribute("testName")
    from unitTest in result.Descendants(ns + "UnitTest")
    where (string)unitTest.Attribute("name") == name
    select unitTest;

var unitTest = unitTestQuery.Single();