Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
XPath:查找以下不带';I don’我不遵循订单模式_Xpath_Axes - Fatal编程技术网

XPath:查找以下不带';I don’我不遵循订单模式

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>

这是用于C代码检测的。我试图标记没有中断的案例陈述。当break语句前面有多行时,树的层次结构如下所示。这是C语言中的一个示例:

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>