【发布时间】:2011-10-25 17:01:24
【问题描述】:
我想检查文档中是否有内联样式表,但我不确定如何选择元素的后代属性,因为“样式”属性可以附加到正文元素中的任何元素。这是我写的当前 xpath:
descendant::@*[self::@style]
但是解析器抛出错误说:“轴名称后出现意外的标记“@””。谁能告诉我如何解决它或有另一种方法可以做到这一点?谢谢!
【问题讨论】:
标签: xml xpath schematron
我想检查文档中是否有内联样式表,但我不确定如何选择元素的后代属性,因为“样式”属性可以附加到正文元素中的任何元素。这是我写的当前 xpath:
descendant::@*[self::@style]
但是解析器抛出错误说:“轴名称后出现意外的标记“@””。谁能告诉我如何解决它或有另一种方法可以做到这一点?谢谢!
【问题讨论】:
标签: xml xpath schematron
使用这个XPath://@style,它将选择所有属性style
【讨论】:
因此,我认为您正在文档中的任何位置查找具有@style 属性的任何元素。
如果你想要包含你想要的属性的元素如下:
descendant::*[@style]
这将返回当前节点的所有具有@style 属性的后代元素。如果你想要属性本身,你最好使用类似的东西:
descendant::*[@style]/@style
它会为您找到所有样式属性本身。
【讨论】:
descendant::* 会给出错误的答案,除非上下文节点是/,在这种情况下它等同于//*。 /descendant::*[@style]/@style 相当于/descendant::*/@style 相当于//*/@style 相当于//@style。
@Kirill 给出了关于如何修复的正确答案
descendant::@*[self::@style]
通过使用
//@style
但是对于那些想知道为什么初始 XPath 不起作用的人,以及是否有使用 self:: 的变体可以工作...
请记住,@ 是 attribute:: 轴的缩写。所以self::@foo 是self::attribute::foo 的简写。但从句法上讲,定位步骤中只能有一个轴。这就是解析器拒绝 self::@style 的原因:它有两个轴。
这里还有其他有趣的事情发生。您可能认为您可以将表达式修复如下:
//@*[self::style]
(暂时忽略这比//@style 更复杂的事实。当您想要所有属性除了style,例如//@*[not(self::style)] 时,您开始尝试这样的表达式。)
这个表达式解析和运行没有错误。第一部分 //@* 匹配文档中的所有属性节点。您可能会认为(和我一样)谓词 [self::style] 将在其上下文节点是 style 属性时评估为真值。
但我们会错的。如果我们尝试一下,我们会得到一个空的节点集。为什么?如果上下文节点是一个属性节点,并且self:: 轴仅包含上下文节点,并且属性的名称与self:: 之后的名称匹配,那么谓词中的表达式不应该将该属性节点作为其结果?
在第页。 XSLT 2.0 和 XPath 2.0(第 4 版)的 1228,Self Axis 的词汇表定义解释:
self轴的主节点种类是elements,表示 当上下文节点是一个属性时,一个轴step 形成
self::*或self::xyz不会选择该属性[粗体强调我的]。
但是,在 XPath 2.0 中,您可以使用 self::attribute(style)。 IE。您可以使用 KindTest 而不是 NameTest。
Michael Kay 详细介绍了 p 上的 NameTest 可以匹配哪些类型的节点的规则。 695.
【讨论】: