问题 XPath并选择单个节点


我在.NET中使用XPath来解析XML文档,其方式如下:

XmlNodeList lotsOStuff = doc.SelectNodes("//stuff");

foreach (XmlNode stuff in lotsOStuff) {
   XmlNode stuffChild = stuff.SelectSingleNode("//stuffChild");
   // ... etc
}

问题是XPath查询 stuffChild 总是回到第一个孩子 stuff 元素,永远不会休息。 XPath不能用于查询个人 XMLElement


1281
2017-08-25 20:32


起源



答案:


// 在XPath表达式的开头,从文档根开始。试试“.//stuffChild”。 。 self :: node()的简写,它将设置搜索的上下文,//是后代轴的简写。

所以你有了:

XmlNode stuffChild = stuff.SelectSingleNode(".//stuffChild");

转换为:

xmlNode stuffChild = stuff.SelectSingleNode(“self :: node()/ descendant :: stuffChild”);

xmlNode stuffChild = stuff.SelectSingleNode("self::node()/descendant-or-self::stuffChild");

在子节点可以与父节点具有相同名称的情况下,您可能希望使用后面稍微详细的语法,以确保您不重新选择父节点:

xmlNode stuffChild = stuff.SelectSingleNode("self::node()/descendant::stuffChild");

另请注意,如果“stuffChild”是“stuff”的直接后代,则可以完全省略前缀,只需选择“stuffChild”即可。

XmlNode stuffChild = stuff.SelectSingleNode("stuffChild");

W3Schools的 教程以易于理解的格式提供有用的信息。


10
2017-08-25 20:35



.//foo是 不 等于后代:: foo并且通常是 错误 选择后代节点的方法。看到 stackoverflow.com/questions/453191 - Azat Razetdinov
也许你错过了。,它设置了以下XPath的上下文? - Chris Marasti-Georg
请参阅//缩写的文档。 .//foo转换为self :: node()/ descendant-or-self :: node()/ child :: stuffChild - Azat Razetdinov
你是对的 - 更新答案。请注意.//将适用于提问者的情况(子节点具有与上下文节点不同的名称)。 - Chris Marasti-Georg


答案:


// 在XPath表达式的开头,从文档根开始。试试“.//stuffChild”。 。 self :: node()的简写,它将设置搜索的上下文,//是后代轴的简写。

所以你有了:

XmlNode stuffChild = stuff.SelectSingleNode(".//stuffChild");

转换为:

xmlNode stuffChild = stuff.SelectSingleNode(“self :: node()/ descendant :: stuffChild”);

xmlNode stuffChild = stuff.SelectSingleNode("self::node()/descendant-or-self::stuffChild");

在子节点可以与父节点具有相同名称的情况下,您可能希望使用后面稍微详细的语法,以确保您不重新选择父节点:

xmlNode stuffChild = stuff.SelectSingleNode("self::node()/descendant::stuffChild");

另请注意,如果“stuffChild”是“stuff”的直接后代,则可以完全省略前缀,只需选择“stuffChild”即可。

XmlNode stuffChild = stuff.SelectSingleNode("stuffChild");

W3Schools的 教程以易于理解的格式提供有用的信息。


10
2017-08-25 20:35



.//foo是 不 等于后代:: foo并且通常是 错误 选择后代节点的方法。看到 stackoverflow.com/questions/453191 - Azat Razetdinov
也许你错过了。,它设置了以下XPath的上下文? - Chris Marasti-Georg
请参阅//缩写的文档。 .//foo转换为self :: node()/ descendant-or-self :: node()/ child :: stuffChild - Azat Razetdinov
你是对的 - 更新答案。请注意.//将适用于提问者的情况(子节点具有与上下文节点不同的名称)。 - Chris Marasti-Georg


// 你在前面使用 stuffChild 意味着你在寻找 stuffChild 元素,从根开始。

如果要从当前节点(当前节点的后代)开始,则应使用 .//,如:

stuff.SelectSingleNode(".//stuffChild");

2
2017-08-25 20:37





如果“stuffChild”是“stuff”的子节点,那么你的xpath应该是:

XmlNode stuffChild = stuff.SelectSingleNode("stuffChild");

1
2017-08-25 20:38





选择单个节点意味着您只需要第一个元素。所以,最好的解决方案是:

XmlNode stuffChild = stuff.SelectSingleNode("descendant::stuffChild[1]");

-1
2018-02-27 20:19