【问题标题】:Best way test for XPath existence in an XML file?测试 XML 文件中是否存在 XPath 的最佳方法?
【发布时间】:2008-10-28 22:09:19
【问题描述】:

最近我一直在使用 XPathDocument 和 XNavigator 为给定的 XPath 和属性解析 XML 文件。当我提前知道 XPath 是什么时,它一直运行良好。

但有时,XPath 将是几个可能的 XPath 值之一,我希望能够测试给定的 XPath 是否存在。

如果我弄错了命名法,这就是我所说的 XPath - 给定这个 XML blob:

<foo>
    <bar baz="This is the value of the attribute named baz">
</foo>

我可能正在寻找我称之为“//foo/bar”的 XPath,然后读取属性“baz”以获取值。

我用来执行此操作的代码示例:

XPathDocument document = new XPathDocument(filename);
XPathNavigator navigator = document.CreateNavigator();
XPathNavigator node = navigator.SelectSingleNode("//foo/bar");
if(node.HasAttributes)
{
    Console.WriteLine(node.GetAttribute("baz", string.Empty));
}

现在,如果对 navigator.SelectSingleNode 的调用失败,它将返回 NullReferenceException 或 XPathException。我可以同时捕获这两个并将上面的内容重构为一个测试,以查看给定的 XPath 是否返回异常,但我想知道是否有更好的方法?

我没有在 Intellisense 中看到任何明显的东西。 XPathNavigator 具有 .HasAttributes 和 .HasChildren 但没有一次遍历一个节点的路径,我没有看到更好的使用方法。

【问题讨论】:

  • 这与 LINQ 有什么关系? XPathNavigator 和 XPathDocument 不是 LINQ to XML 的一部分。

标签: c# xml


【解决方案1】:

如果您提供了有效的 XPath,但它不匹配任何内容,SelectSingleNode 将不会抛出 NullReferenceException - 它只会返回 null。

如果您传递 SelectSingleNode 一些语法上无效的 XPath,那么它将抛出 XPathException

所以通常情况下,您只需要测试返回的值是否为空。

【讨论】:

    【解决方案2】:
     var baz = navigator.SelectSingleNode("//foo/bar/@baz");
     if (baz != null) Console.WriteLine(baz);
    

    【讨论】:

      【解决方案3】:

      我觉得通过执行navigator.SelectSingleNode(...)来创建XMLNode对象不好。

      你必须使用 navigator.Evaluate() 代替:

      if (Convert.ToBoolean(navigator.Evaluate(@"boolean(//foo/bar)"))) {...}
      

      【讨论】:

      • 我对这种方法与 SelectSingleNode 进行了速度比较,每次迭代 500,000 次(XPath 表达式为字符串,未编译)。 SelectSingleNode 方法比布尔方法快 16-18%。我已经重复测试了几次,结果是一致的。
      【解决方案4】:

      凭记忆,可能有错误。

      XDocument doc = XDocument.Load("foo.xml");
      
      var att = from a in doc.Descendants("bar")
                select a.Attribute("baz")
      
      foreach (var item in att) {
          if (item != null) { ... }
      }
      

      【讨论】:

      • 由于问题标题提到了Linq,这就是我的做法。
      • 如果只需要一个,请在查询中使用 .FirstOrDefault
      【解决方案5】:

      如果node == nullnode.HasAttributes 将抛出NullReferenceException。当//foo/bar 不匹配 XML 文档中的任何元素时,就会出现这种情况。

      【讨论】:

        【解决方案6】:
        var node = XDocument.Load(filename)
                            .Descendants("bar")
                            .SingleOrDefault(e=>e.Attribute("baz") != null);
        
        if (node != null) Console.WriteLine(node.Attribute("baz").Value);
        

        【讨论】:

          【解决方案7】:

          我可能会在我的 xpath 中更具体。

                  var doc = XDocument.Load(fileName);
          
                  var results = from r in doc.XPathSelectElements("/foo/bar[count(@baz) > 0]")
                                select r.Attribute("baz");
          
                  foreach (String s in results)
                      Console.WriteLine(s);
          

          【讨论】:

            猜你喜欢
            • 2010-12-13
            • 2011-03-23
            • 2011-04-26
            • 2015-04-06
            • 1970-01-01
            • 2016-02-04
            • 1970-01-01
            相关资源
            最近更新 更多