Search code examples
xpathaxes

XPath : Find following siblings that don't follow an order pattern


This is for C code detection. I'm trying to flag case statements that don't have a break. The hierarchy of the tree looks like this when there are multiple lines before the break statement. This is an example in C:

switch (x) {
  case 1:
    if (...) {...}
    int y = 0;
    for (...) {...}
    break;
  case 2:

It is somehow represented as this:

<switch>
  <case>...</case>
  <if>...</if>
  <expression>...</expression>
  <for>...</for>
  <break>...</break>
  <case>...</case>
</switch>

I need to find <case>s where a <break> exists after any number of lines, but before the next <case>.

This code only helps me find those where the break doesn't immediately follow the case:

//case [name(following-sibling::*[1]) != 'break']

..but when I try to use following-sibling::* it will find a break, but not necessarily before the next case.

How can I do this?


Solution

  • Select any case that has a following break and either no following case or where the position of the next break is less than the position of the next case. With the positions determined by running count() on the preceding siblings.

    //case
    [
        following-sibling::break and
        (
            not(following-sibling::case) or
            (
                count(following-sibling::break[1]/preceding-sibling::*) <
                count(following-sibling::case[1]/preceding-sibling::*)
            )
        )
    ]
    

    To grab the other cases, those without breaks, just throw a big old not() in there like so:

    //case
    [not(
        following-sibling::break and
        (
            not(following-sibling::case) or
            (
                count(following-sibling::break[1]/preceding-sibling::*) <
                count(following-sibling::case[1]/preceding-sibling::*)
            )
        )
    )]