XPath:查找以下不带';I don’我不遵循订单模式
这是用于C代码检测的。我试图标记没有中断的案例陈述。当break语句前面有多行时,树的层次结构如下所示。这是C语言中的一个示例:XPath:查找以下不带';I don’我不遵循订单模式,xpath,axes,Xpath,Axes,这是用于C代码检测的。我试图标记没有中断的案例陈述。当break语句前面有多行时,树的层次结构如下所示。这是C语言中的一个示例: switch (x) { case 1: if (...) {...} int y = 0; for (...) {...} break; case 2: 它以某种方式表现为: <switch> <case>...</case> <if>...</if>
switch (x) {
case 1:
if (...) {...}
int y = 0;
for (...) {...}
break;
case 2:
它以某种方式表现为:
<switch>
<case>...</case>
<if>...</if>
<expression>...</expression>
<for>...</for>
<break>...</break>
<case>...</case>
</switch>
…但当我尝试使用以下兄弟姐妹::*它会找到一个休息,但不一定在下一个案例之前
我怎样才能做到这一点呢?我认为您正在苦苦挣扎,因为您的XML格式并不能很好地模拟问题。如果其他语句嵌套在
元素中,而不是嵌套在兄弟元素中,那么使用switch/case[break]
就容易多了
在当前结构中,最简单的方法是首先查找
,然后向后查找匹配的
。正如@LarsH所指出的,我最初的表达会发现一些附加条款。除非您将其限制为仅查找第一种情况,否则无法对其进行修改以解决此问题:
switch/break/preceding-sibling::case[1]
@derp的答案更好,可以找到有中断和没有中断的情况。选择任何有后续
中断
且没有后续中断
或下一个中断
位置小于下一个中断
位置的案例。通过在前面的同级上运行count()
确定位置
//case
[
following-sibling::break and
(
not(following-sibling::case) or
(
count(following-sibling::break[1]/preceding-sibling::*) <
count(following-sibling::case[1]/preceding-sibling::*)
)
)
]
德普的回答是正确的。但我会再加一个。这将选择具有中断的案例元素:
//case[generate-id(.) =
generate-id(following-sibling::break[1]/preceding-sibling::case[1])]
换言之,这将选择适用于以下情况的案例元素:
上下文元素与下一个break元素之前的第一个case元素相同(仅考虑同级)
如果您有很多case语句,则此变体可能比使用count()
更快。但除非使用相关XPath处理器使用相关数据对其进行测试,否则您永远无法确定
顺便说一句,生成id(.)
中的
不是必需的,因为参数默认为
。但是为了可读性,我更喜欢将其显式化。我同意@PeterHall的观点,最好将XML重新构造成更接近C语法的抽象语法树。通过XSLT分组,您可以很容易地做到这一点(在这种情况下):
<xsl:for-each-group select="*" group-starting-with="case">
<case>
<xsl:copy-of select="current-group()[not(self::case)]"/>
</case>
</xsl:for-each-group>
然后可以找到没有中断的案例,如switch/case[not(break)]
?此外,你的第一段说你正在寻找没有中断的案例陈述;你的第三段说你正在寻找那些能做到的。这可能意味着几乎相同的事情,但清晰会有所帮助。好点@LarsH,我更新了我的答案以反映局限性。很抱歉造成混淆。我试图从查找中断开始,认为我应该在语句中添加一个NOT来查找那些没有中断的语句。通常,这个XPath表达式可以生成有中断的case语句和没有中断的case语句(但后面跟着另一个有中断的case)。感谢derp,我不认为要将断裂的位置与下一个案例进行比较。这帮我解决了我的问题!
//case[generate-id(.) =
generate-id(following-sibling::break[1]/preceding-sibling::case[1])]
<xsl:for-each-group select="*" group-starting-with="case">
<case>
<xsl:copy-of select="current-group()[not(self::case)]"/>
</case>
</xsl:for-each-group>