我有一个xml文件,格式如下
<someXML>
<a>
<b></b>
<b test='someValue'></b>
</a>
<c>
<d test='someOtherValue'></d>
<d></d>
</c>
</someXML>
我正在尝试编写C#代码,它将为我提供一个仅包含具有test属性的节点的节点集。我试图以这种方式使用XPathExpression:
XDocument document = XDocument.Load("someXML");
XPathNavigator navigator = document.CreateNavigator();
XPathExpression expression = XPathExpression.Compile("//*[@test]");
object nodeSet = navigator.Evaluate(expression);
这似乎不起作用。调试时,nodeSet始终包含Root元素。表达式有问题或者这是否正常工作?
谢谢!
答案 0 :(得分:4)
您是否认为nodeSet
包含“Root”元素,因为调试器将其字符串表示形式显示为Position=0, Current={Root}
?这可能会产生误导;出现“Root”元素的原因是因为XPathNodeIterator
(在您的情况下由Evaluate
返回的实际类型)尚未定位在查询产生的第一个节点上。根据{{3}}的MSDN文档:
XPathNodeIterator
类返回的XPathNavigator
对象不位于选定节点集中的第一个节点上。必须调用MoveNext
类的XPathNodeIterator
方法,将XPathNodeIterator
对象放在所选节点集中的第一个节点上。
您可以通过迭代nodeSet
:
XDocument document = XDocument.Load("someXML");
XPathNavigator navigator = document.CreateNavigator();
XPathExpression expression = XPathExpression.Compile("//*[@test]");
XPathNodeIterator nodeSet = (XPathNodeIterator)navigator.Evaluate(expression);
foreach (XPathItem item in nodeSet)
{
// Process item here
}
或者,如果您希望将它们转换为数组:
XDocument document = XDocument.Load("someXML");
XPathNavigator navigator = document.CreateNavigator();
XPathExpression expression = XPathExpression.Compile("//*[@test]");
XPathNodeIterator nodeSet = (XPathNodeIterator)navigator.Evaluate(expression);
XPathItem[] items = nodeSet.Cast<XPathItem>().ToArray();
答案 1 :(得分:4)
您的XPath 确实有效,只需要稍微检索一下节点:
XPathNavigator navigator = document.CreateNavigator();
XPathExpression expression = XPathExpression.Compile("//*[@test]");
var matchedNodes = navigator.Select(expression);
foreach (XPathNavigator node in matchedNodes)
{
Console.WriteLine(node.UnderlyingObject);
}
上面的代码段将打印以下内容:
<b test='someValue'></b>
<d test='someOtherValue'></d>
答案 2 :(得分:3)
你的表情似乎是正确的。但您可以使用XPathSelectElements
扩展方法来简化:
var nodes = document.XPathSelectElements("//*[@test]");
答案 3 :(得分:2)
您的XPath查询是正确的。 Current成员将是Root元素(我不是XPathIterator专家,所以我真的不知道它背后的基本原理)。如果遍历nodeSet,则只能获得与XPath查询匹配的内容。所以我想答案是迭代集合并将每个项目放入集合中。
答案 4 :(得分:1)
我相信你会想要使用XPathNavigator对象的Select方法,而不是Evaluate,它将返回一个XPathNodeIterator对象。
http://msdn.microsoft.com/en-us/library/3tk3f03k.aspx
或者您可以使用XmlDocument对象和XmlNodeList:
XmlDocument document = new XmlDocument();
document.Load("somexml.xml");
XmlNodeList nodeList = document.SelectNodes("//*[@test]");
foreach (XmlNode Node in nodeList) {
// do something.
}
答案 5 :(得分:0)
为什么不这样做,假设您只是想要节点并且没有特定的理由使用导航器(null检查省略):
var document = XDocument.Load("someXML");
var myNodes = document.Descendants().Where(node => node.Attribute(myAttributeName) != null);
它不使用导航器,但如果您只是想要节点,那么它非常简单明了。