Christian, I love the contains token! Didn't know about that.
The reason I'm looking for a switch instead of the if then else is more for readability, there are a lot of elements and classes in DITA, when you're indenting to character 2xx it starts to get hard to manage! Maybe I'll bug people on the xquery side with this case. DITA is popular enough that it should matter.
Mark, good point, values for @ class in DITA start and end with spaces, and you always match on space-value-space. I omitted the spaces to focus on my current issue, but it looks like you have a bionic eye for finding potential issues :-P.
Thank you for your feedback on this!
On Fri, Mar 13, 2015 at 4:52 AM, Christian Grün christian.gruen@gmail.com wrote:
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