tags:

views:

80

answers:

3

Hello,

I have sample XML like this:

<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>

Is there any way to get all users who are in role GUEST using XPath expression ?

+1  A: 

This XPath expression will select all users whose roles node contains GUEST.

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

See the contains xpath function.

Oded
@Oded: I think you should say that this works if there is no other role having "GUEST" as a part, like "EXTERNALGUEST" that it was commented.
Alejandro
A: 

If you're able to use XSLT 2.0 I would suggest you to tokenize the string of roles. Using contains() is fine as long as you don't start having role names like "EXTERNALGUEST" or similar since it would match that aswell.

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

This XPath will tokenize the roles depending on the @separator and return the users which has this role.

Per T
Unfortunately I have an error while I'm trying to use tokenize function with c#.
Jarek Waliszko
Oh, I belive that you need to use XSLT 1.0 if you gonna implement this in C#. If you don't wanna use Saxon .Net. I don't think it's possible to solve this issue with a simple XPath expression in 1.0, but I'd be glad to be proven wrong.However, it is possible to solve using recursive templates in XSLT 1.0.
Per T
+2  A: 

Use:

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

This selects all desired user nodes, regardless whether 'GUEST' is the only role or it is at the start, in the middle or at the end of the string.

Dimitre Novatchev
@Dimitre Novatchev: I belive you actully ment: `/users/user[roles[contains(concat(@separator, ., @separator), concat(@separator, 'GUEST', @separator))]]/@name` since your XPath is broken. But I'll give you +1 anyway because I didn't come up with the idea... ;)
Per T
@Per-T: Thanks for noticing this -- I was very tired and sleepy yesterday when replying... :(
Dimitre Novatchev
@Dimitre: +1 Excellent answer! I was expecting that you would come with something smart like this.
Alejandro