2012-01-09 108 views
3

我用這個XPath表達式來列出所有「無試驗」項目:我XPATH表達不能正常工作

/Items/Item[State!='TEST']/Name 

通常輸入XML看起來是這樣的,一切工作正常:

<Items> 
    <Item> 
    <Name>Item1</Name> 
    <State>ACTIVE</State> 
    </Item> 
    <Item> 
    <Name>Item2</Name> 
    <State>TEST</State> 
    </Item> 
</Items> 

但Item錯過State元素時,xpath表達式不會選擇任何內容:

<Items> 
    <Item> 
    <Name>Item1</Name> 
    </Item> 
    <Item> 
    <Name>Item2</Name> 
    </Item> 
</Items> 

請問我該如何更改我的xpath表達式n,以便State元素不存在時它也可以工作?如果狀態元素不存在則將項目視爲「不測試」項目。我沒有選擇更改xml結構。

回答

5

使用下面的表達式:

/Items/Item[not(State='TEST')]/Name 

的區別在於State!='TEST'選擇具有任何State元件,其字符串值不等於TEST的那些項目,而not(State='TEST')選擇不具有State元件,其字符串值的所有項目等於TEST(是否存在State)。這是一個微妙但顯着的差異。

the spec

如果一個要比較的對象是一個節點集合,而另一個是一個字符串, 則比較爲真,當且僅當存在在 節點的節點 - 設置,以便對節點的字符串值和其他字符串執行比較的結果爲true。

此外,設想以下輸入:

<Items> 
    <Item> 
     <Name>Item1</Name> 
     <State>blah</State> 
     <State>TEST</State> 
    </Item> 
    <Item> 
     <Name>Item2</Name> 
     <State>TEST</State> 
    </Item> 
</Items> 

該表達式:

/Items/Item[State!='TEST']/Name 

...將選擇第一ItemName元件,因爲它包含至少一個State元素值不爲TEST

然而,這個表達式:

/Items/Item[not(State='TEST')]/Name 

...選擇任何項目。第二種形式通常是你想要的。

見本說明from the spec

注:如果$x綁定到節點集,然後$x="foo"並不意味着 一樣not($x!="foo"):前者爲真,當且僅當一些節點 $x具有字符串值foo;後者是真實的當且僅當全部 $x中的節點具有字符串值foo

+0

+1,很好的答案。你確定關於語句「State!='TEST''選擇那些其(第一)狀態元素的值不等於TEST的項目」嗎?我認爲它選擇那些具有* any *'State'子元素的整個值不等於'TEST'的項目。換句話說,我相信比較中的節點測試不會摺疊爲字符串值,以至於不能排除存在性比較。 – LarsH 2012-01-09 20:48:49

+0

@LarsH - 當然你是對的。更新。 – 2012-01-09 21:01:37

+0

它的工作原理!非常感謝你們的幫助! – Vojtech 2012-01-10 10:59:44