2010-08-04 63 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