【问题标题】:XPath expression for selecting all nodes with a common attribute用于选择具有公共属性的所有节点的 XPath 表达式
【发布时间】:2010-10-22 21:59:42
【问题描述】:

我正在阅读的一本关于 XML 的书说,要选择 XML 文件中具有特定属性的所有节点,请使用以下语法:

//*/@_attribute_

我不明白为什么需要星号。据我了解,表达式 // 选择根节点的所有后代。那么,例如, //@lang 不会选择具有名为“lang”的属性的根节点的所有后代吗?我什至无法解释星号在上述表达式中的含义(我知道星号通常表示“全部”)。如果有人能为我分解它,我将不胜感激。

谢谢

【问题讨论】:

  • 好问题,+1。请参阅我的回答,以更正@Alejandro 的声明,即您的 XPath 表达式是“错误的”。 @Alejandro 的回答很好,只是这个 XPath 表达式没有问题。

标签: xml xpath


【解决方案1】:

嗨,我正在阅读的一本关于 XML 的书说 选择 XML 中的所有节点 具有特定属性的文件, 使用语法:

//*/@attribute

错了。它将扩展为:

/descendant-or-self::node()/child::*/attribute::attribute

含义:节点的任何元素子元素的所有attribute 属性是根文档本身或其后代之一

你需要:

/descendant::*[attribute::attribute]

或缩写形式

//*[@attribute]

关于*:正式地是一个名称测试而不是一个节点类型测试。在 XPath 1.0 中没有元素类型测试。在 XPath 2.0 中,您有 element()。那么,为什么只选择元素呢?好吧,它没有。轴有一个主节点类型,来自http://www.w3.org/TR/xpath/#node-tests

每个轴都有一个主节点类型。 如果一个轴可以包含元素,那么 主节点类型为元素; 否则,它是节点的类型 轴可以包含的。因此,

  • 对于属性轴,主节点类型为属性。
  • 对于命名空间轴,主节点类型是命名空间。
  • 对于其他轴,主节点类型为元素。

这就是为什么 *child::*self::*descendant::* 等选择元素,但 @*attribute::*namespace::* 选择属性或范围内的命名空间。

关于谓词([@attribute] 部分):此表达式是对上一步选择的每个节点进行评估的。它需要一个用于过滤的布尔值。节点集的布尔值(这是 attribute::attribute 的结果)对于空节点集为 false,否则为 true。

【讨论】:

  • @Alejandro。 //*/@x 没有没有错误,只是它比它可能的更长。
【解决方案2】:

这道题的题目是

选择所有的 XPath 表达式 具有共同属性的节点

但是,问题的文本没有讨论如何找到具有共同属性的所有节点——因此标题可能不正确。

要查找具有名为x 的公共属性的所有节点(顺便说一句,只有元素节点可以具有属性),使用

//*[@x]

使用

//@x

选择 XML 文档中名为 x 的所有属性。这可能是最短的表达方式。

没有错

//*/@x

除了稍微长一点。

它是的简写:

/descendant-or-self::node()/child::*/attribute::x

并且还选择 XML 文档中的所有 x 属性。

有人可能会认为这个表达式没有选择文档中顶部元素的x 属性。这是一个错误的结论,因为第一个位置步骤:

/descendant-or-self::node()

选择文档中的每个节点,包括 (/) 本身。

这意味着:

/descendant-or-self::node()/child::*

选择每个元素,包括顶部元素(它是格式良好的 XML 文档中根节点的唯一子节点)。

所以,当最后一个位置步骤/@x最终添加时,这将选择前两个位置步骤迄今为止选择的所有节点的所有x属性——即所有元素的所有x属性-XML 文档中的节点。

【讨论】:

  • +1 感谢您的澄清。我总是喜欢阅读你的答案。
猜你喜欢
  • 2016-10-03
  • 1970-01-01
  • 2012-02-18
  • 2011-01-30
  • 2012-02-20
  • 1970-01-01
  • 1970-01-01
  • 2013-10-11
  • 2013-11-30
相关资源
最近更新 更多