2010-08-04 62 views
2

我有樣本XML這樣的:XPath表達式 - 幫助需要

<users> 
    <user name="user1"> 
     <roles separator=",">ADM,USER</roles> 
    </user> 
    <user name="user2"> 
     <roles separator=",">ADM,GUEST</roles> 
    </user> 
    <user name="user3"> 
     <roles separator=",">READER,GUEST</roles> 
    </user> 
</users> 

有沒有辦法讓所有用戶誰在使用角色XPath表達式GUEST

+0

好問題(+1)。請參閱我的答案,瞭解簡短且正確的XPath 1.0單行程。 :) – 2010-08-04 23:02:33

+0

我已修復@ Per-T發現的問題 - 現在我的答案提供了一個非常好的XPath 1.0解決方案。 – 2010-08-05 12:53:29

回答

0

如果您能夠使用XSLT 2.0,我建議您標記一串角色。使用是好的,只要你沒有像「EXTERNALGUEST」或類似名稱那樣開始角色名稱,因爲它也可以匹配。

/users/user[tokenize(roles, roles/@separator) = 'GUEST']/@name 

此XPath會在標記化取決於roles@separator並返回擁有這個角色的用戶。

+0

不幸的是,我試圖在c#中使用標記化函數時出現錯誤。 – jwaliszko 2010-08-04 09:45:31

+0

哦,我相信你需要使用XSLT 1.0,如果你要在C#中實現這一點。如果你不想使用Saxon .Net。 我不認爲用1.0中簡單的XPath表達式可以解決這個問題,但我很樂意被證明是錯誤的。 但是,可以使用XSLT 1.0中的遞歸模板來解決問題。 – 2010-08-04 10:32:54

1

該XPath表達式將選擇其角色節點包含GUEST的所有用戶。

//user[contains(roles, 'GUEST')] 

查看contains xpath函數。

+0

我認爲你應該說這是有效的,如果沒有其他角色具有「GUEST」作爲一部分,就像它被評論的「EXTERNALGUEST」一樣。 – 2010-08-04 15:21:35

1

使用

/users/user/[roles[contains(concat(@separator, ., @separator), 
          concat(@separator, 'GUEST', @separator) 
          ) 
        ] 
      ] 

這將選擇所有需要的user節點,無論是否'GUEST'是唯一的角色,或者是在開始,中間或字符串結束。

+0

我相信你的行爲:'/ users/user [roles [contains(concat(@separator,。,@separator),concat(@separator,'GUEST',@separator))]]/@ name'自XPath被打破。但無論如何,我會給你+1,因爲我沒有想出這個主意......;) – 2010-08-05 11:46:51

+0

@ Per-T:感謝你注意到這一點 - 昨天我很疲倦,睏倦時回答...... :( – 2010-08-05 12:51:15

+0

+1優秀的答案!我期待着你會有這樣聰明的東西來。 – 2010-08-05 16:01:07