C# 测试 XML 文件中 XPath 存在的最佳方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/245058/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best way test for XPath existence in an XML file?
提问by Mark Allen
Lately I've been using XPathDocument and XNavigator to parse an XML file for a given XPath and attribute. It's been working very well, when I know in advance what the XPath is.
最近,我一直在使用 XPathDocument 和 XNavigator 来解析给定 XPath 和属性的 XML 文件。当我事先知道 XPath 是什么时,它一直工作得很好。
Sometimes though, the XPath will be one of several possible XPath values, and I'd like to be able to test whether or not a given XPath exists.
但有时,XPath 将是几个可能的 XPath 值之一,我希望能够测试给定的 XPath 是否存在。
In case I'm getting the nomenclature wrong, here's what I'm calling an XPath - given this XML blob:
万一我弄错了命名法,这就是我所说的 XPath - 鉴于此 XML blob:
<foo>
<bar baz="This is the value of the attribute named baz">
</foo>
I might be looking for what I'm calling an XPath of "//foo/bar" and then reading the attribute "baz" to get the value.
我可能正在寻找我称之为“//foo/bar”的XPath,然后读取属性“baz”以获取值。
Example of the code that I use to do this:
我用来执行此操作的代码示例:
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));
}
Now, if the call to navigator.SelectSingleNode fails, it will return a NullReferenceException or an XPathException. I can catch both of those and refactor the above into a test to see whether or not a given XPath returns an exception, but I was wondering whether there was a better way?
现在,如果对 navigator.SelectSingleNode 的调用失败,它将返回 NullReferenceException 或 XPathException。我可以捕获这两个并将上述内容重构为测试,以查看给定的 XPath 是否返回异常,但我想知道是否有更好的方法?
I didn't see anything obvious in the Intellisense. XPathNavigator has .HasAttributes and .HasChildren but short of iterating through the path one node at a time, I don't see anything nicer to use.
我在智能感知中没有看到任何明显的东西。XPathNavigator 有 .HasAttributes 和 .HasChildren ,但没有一次遍历一个节点的路径,我看不出有什么好用的。
采纳答案by Jon Skeet
If you've given valid XPath but it doesn't match anything, SelectSingleNode
won't throwa NullReferenceException
- it will just return null.
如果你给了有效的XPath,但它不匹配任何东西,SelectSingleNode
也不会抛出一个NullReferenceException
-它只是返回null。
If you pass SelectSingleNode
some syntactically invalid XPath, that's when it will throw an XPathException
.
如果您传递SelectSingleNode
一些语法上无效的 XPath,那么它将抛出一个XPathException
.
So normally, you'd just need to test whether the returned value was null or not.
所以通常情况下,您只需要测试返回的值是否为空。
回答by John Sheehan
From memory, may contain errors.
根据记忆,可能包含错误。
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) { ... }
}
回答by yfeldblum
If node == null
then node.HasAttributes
will throw a NullReferenceException
. This situation will occur when //foo/bar
does not match any elements in the XML document.
如果node == null
然后node.HasAttributes
会抛出一个NullReferenceException
. 当//foo/bar
与 XML 文档中的任何元素都不匹配时,就会出现这种情况。
回答by Mark Cidade
var node = XDocument.Load(filename)
.Descendants("bar")
.SingleOrDefault(e=>e.Attribute("baz") != null);
if (node != null) Console.WriteLine(node.Attribute("baz").Value);
回答by Mark Cidade
var baz = navigator.SelectSingleNode("//foo/bar/@baz");
if (baz != null) Console.WriteLine(baz);
回答by Mark Cidade
I would probably be more specific in my xpath.
我可能会在我的 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);
回答by Ron
I think it is not good to create an XMLNode object by executing navigator.SelectSingleNode(...).
我认为通过执行 navigator.SelectSingleNode(...) 创建 XMLNode 对象并不好。
You have to use navigator.Evaluate() instead:
您必须改用 navigator.Evaluate() :
if (Convert.ToBoolean(navigator.Evaluate(@"boolean(//foo/bar)"))) {...}