2014-09-01 48 views
3

這是用於C代碼檢測的。我試圖標記沒有休息的案例陳述。當break語句之前有多行時,樹的層次結構如圖所示。這是C中的例子:XPath:查找以下不遵循訂單模式的兄弟姐妹

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> 

我需要找到<case> S其中任意數量的行後存在<break>,而是先下一<case>

此代碼僅可以幫助我找到那些破不立即跟隨的情況下:

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

..但是,當我嘗試使用以下同胞:: *它會找到一個突破,但不一定在下一個案件之前。

我該怎麼做?

+0

你可以使用XPath 2.0還是你堅持1.0?此外,你的第一段說你正在尋找*不*休息的病例陳述;你的第三段說你正在尋找那些*做*。它可能相當於幾乎相同的東西,但清晰度會有所幫助。 – LarsH 2014-09-02 03:52:16

+0

好點@LarsH,我更新了我的答案以反映這個限制。 – 2014-09-02 13:07:58

+0

對不起,困惑。我試圖從找到休息開始,認爲我只是在聲明中添加一個NOT來找到那些沒有休息的人。 – user2755941 2014-09-02 20:38:18

回答

2

選擇具有任何case一個以下break要麼沒有以下case或下一個break的位置小於下一case的位置。通過在前面的兄弟姐妹上運行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::*) 
     ) 
    ) 
] 

其他箱子,那些沒有斷裂,只是拋出一個巨大的老not()在那裏,像這樣:

//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::*) 
     ) 
    ) 
)] 
+0

非常感謝derp,我沒有想過要比較下一個案例的中斷位置。這幫助我解決了我的問題! – user2755941 2014-09-02 20:44:28

1

我認爲你很掙扎,因爲你的XML格式並沒有很好地模擬這個問題。如果其他語句嵌套在<case>元素中,而不是兄弟姐妹,那麼您可以僅使用switch/case[break]

使用您當前的結構,最簡單的方法是找到<break>,然後向後找到匹配的<case>。正如@LarsH指出的那樣,我的原始表達式會找到一些額外的子句。它不能真正進行修改,以解決這個問題,除非你限制它找到剛纔第一種情況:

switch/break/preceding-sibling::case[1] 

@ DERP的回答是好,可有或沒有休息發現這兩種情況。

+0

一般來說,這個XPath表達式可能會產生兩個有中斷的case語句,而那些沒有(但後面跟另一個有中斷的情況)的case語句。 – LarsH 2014-09-02 03:56:31

0

DERP的答案是正確的。但我會再添加一個。這將選擇殼體元素做有一個突破:

//case[generate-id(.) = 
     generate-id(following-sibling::break[1]/preceding-sibling::case[1])] 

。換句話說,這種選擇的情況下的元件指此爲真: 上下文元件是相同的下破元件(僅考慮兄妹前述第一殼體元件)。

如果你有很多病例陳述,這個變種可能會比使用count()更快。但是除非您使用相關XPath處理器對相關數據進行測試,否則您永遠無法確定。

順便說一句,.generate-id(.)不是必需的,因爲無論如何參數默認爲.。但爲了可讀性,我更願意明確說明。

1

我同意@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)]