A little addition: XQuery 3.1 provides the function contains-token to
request single values of attributes. It basically does what Marc
proposed [1]:
let $input := <a class='ancestor field'/>
let $class := $input/@class
return if(contains-token($class, 'ancestor')) then (
1
) else if(contains-token($class, 'descendant')) then (
2
) else (
0
)
This is one more way to do it:
let $input := <a class='ancestor field'/>
let $tokens := map:merge(
tokenize($input/@class, '\s+') ! map { .: true() }
)
return if($tokens?ancestor) then (
1
) else if($tokens?descendant) then (
2
) else (
0
)
Best,
Christian
[1] http://docs.basex.org/wiki/XQuery_3.1#fn:contains-token
On Thu, Mar 12, 2015 at 10:45 PM, Marc van Grootel
<marc.van.grootel@gmail.com> wrote:
>
> Hi France,
>
> Typeswitch is not the right tool for this.
>
> From the spec:
>
> [74] TypeswitchExpr ::= "typeswitch" "(" Expr ")" CaseClause+ "default" ("$" VarName)? "return" ExprSingle
> [75] CaseClause ::= "case" ("$" VarName "as")? SequenceTypeUnion "return" ExprSingle
> [76] SequenceTypeUnion ::= SequenceType ("|" SequenceType)*
>
>
> As the name implies it is meant for checking (sequence) types and not for arbitrary XPath expressions.
>
> Also, using contains isn't watertight as contains('foobar','foo') would match as well. I would probably use a function like this
>
> declare function in-class($node as element(), $class as xs:string) as xs:boolean {
> $class = tokenize($node/@class,'\s+')
> }
>
> Do check performance in your situation. In case you need to do many checks on the same class attribute you may want to bind the tokenized value list with a let instead of using this function.
>
> I also remember that Michael Kay is looking into improving on exactly this use case. But that doesn't help you now.
>
> Cheers,
> --Marc
>
> On 12 mrt. 2015, at 20:33, France Baril <france.baril@architextus.com> wrote:
>
> Hi,
>
> I'm working on a new DITA project. The DITA standard is used for technical documentation. It creates XML models with inheritance by using @class="ancestor parent child". If the child should behave like it's ancestor the XSL would say:
> <template match="contains(@class, 'ancestor')"> ... </template>
>
> The advantage is that the model can evolve and when new elements are added, you only need to code transformations for the differences.
>
> I am trying to figure out if I can use type switching with contains in attribute. Search gets me no syntax for something like this:
>
> typeswitch ($node)
> case attribute(contains(class, 'ancestor'))
>
> Maybe I should register to the xquery group to get an answer, but since I'm already here, I though I should ask, and maybe there is a BaseX specific option. I mean other that an unmanageable number of 'if then else' statements.
>
> Thanks!
>
>
>
> --
> France Baril
> Architecte documentaire / Documentation architect
> france.baril@architextus.com