我一直在研究XPath的节点测试(此处为文档(,并在一些示例xml上进行了测试。
<apartment residents="4" shared="true">
fries
<!-- potatosalad -->
</apartment>
虽然属性//apartment/@*的Kindtest将返回居民和共享,这意味着它们都是公寓节点的子级,但任何类型的//公寓/节点((都将返回文本节点炸薯条以及注释节点potatosalad,但不返回属性节点1urident或shared。
这似乎违背了我的直觉,我想知道:这有充分的理由吗?
XPath//apartment/node()
将选择apartment
元素的所有子节点,即*
、processing-instruction()
、comment()
和text()
。
属性和名称空间的特殊之处在于,它们的父元素是它们"是"的元素;附于";,但它们不被视为child节点,并且不会从child轴中选择。
关于规格中的子轴的信息(我添加了粗体以示强调(:
https://www.w3.org/TR/2017/REC-xpath-31-20170321/#axes
子轴包含上下文节点的子节点,这些子节点是第5.3节子访问器返回的节点。
注意:只有文档节点和元素节点具有子节点。如果上下文节点是任何其他类型的节点,或者上下文节点是空文档或元素节点,则子轴是空序列文档节点或元素节点的子节点可以是元素、处理指令、注释或文本节点。属性、命名空间和文档节点永远不能显示为子节点
https://www.w3.org/TR/xpath-datamodel-31/#ElementNodeOverview
- 不包括属性和命名空间节点,如果节点N具有父元素E,则N必须在E的子元素中
"为什么?"问题总是很难回答。我们可以指出规范中的规则,即它就是这样做的,但我们很少能发现委员会在做出决定时的想法,如果真的有意识的话。我们真正能做的就是推测为什么有人会认为这是一个好的设计。
当您意识到node()
是NodeTest
,在这里用作AxisStep
时,这个决定是有意义的。AxisStep
的形式为[Axis::]NodeTest
,Axis
部分默认为"child::"。有一个"子或属性"轴并不是很有用,因为child-or-attribute::XYZ
是不明确的。所以没有,这意味着当NodeTest
恰好是node()
时,将其用作默认轴是没有意义的。
基本上,axis步骤有一个完整的语法,它是高度正交的(你可以将任何axis与任何NodeTest一起使用(,正交性受到语言设计者的高度重视。然后是一个缩写语法,使常见情况不那么冗长;缩写不那么正交,但有一些一致性,其中一个一致性规则是默认轴是子轴,除非(在2.0中(NodeTest只选择属性或名称空间节点。