代码之家  ›  专栏  ›  技术社区  ›  Mark Allen

XML文件中存在xpath的最佳方式测试?

  •  6
  • Mark Allen  · 技术社区  · 16 年前

    最近,我一直在使用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是否返回异常,但我想知道是否有更好的方法?

    我没有看到任何明显的东西。xpathnavigator有.hasattributes和.hasschildren,但除了一次遍历一个节点的路径之外,我看不到更好的用法。

    7 回复  |  直到 8 年前
        1
  •  10
  •   Jon Skeet    16 年前

    如果您提供了有效的xpath,但它与任何内容都不匹配, SelectSingleNode 不会 NullReferenceException -它将返回空值。

    如果你通过 选择单个节点 一些语法上无效的xpath,它将 XPathException .

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

        2
  •  1
  •   Mark Cidade    16 年前
     var baz = navigator.SelectSingleNode("//foo/bar/@baz");
     if (baz != null) Console.WriteLine(baz);
    
        3
  •  1
  •   Ron    8 年前

    我认为通过执行navigator.selectsinglenode(…)来创建xmlnode对象是不好的。

    您必须改用navigator.evaluate():

    if (Convert.ToBoolean(navigator.Evaluate(@"boolean(//foo/bar)"))) {...}
    
        4
  •  0
  •   John Sheehan    16 年前

    从内存中,可能包含错误。

    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) { ... }
    }
    
        5
  •  0
  •   yfeldblum    16 年前

    如果 node == null 然后 node.HasAttributes 会扔 NullReferenceException . 这种情况会发生在 //foo/bar 与XML文档中的任何元素都不匹配。

        6
  •  0
  •   Mark Cidade    16 年前
    var node = XDocument.Load(filename)
                        .Descendants("bar")
                        .SingleOrDefault(e=>e.Attribute("baz") != null);
    
    if (node != null) Console.WriteLine(node.Attribute("baz").Value);
    
        7
  •  0
  •   duyker    16 年前

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