DITA project

Thursday, 12 March 2015 · 6 messages · last reply 14 Mar 2015
FB
France Baril12 Mar 2015 21:34 #
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 at architextus.com
MG
Marc van Grootel12 Mar 2015 22:45 #
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
Quoted text · France Baril · 24 lines
> On 12 mrt. 2015, at 20:33, France Baril <france.baril at 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 at architextus.com
CG
Christian Grün13 Mar 2015 12:52 #
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
  )
Quoted text · Marc van Grootel · 53 lines
On Thu, Mar 12, 2015 at 10:45 PM, Marc van Grootel <marc.van.grootel at 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 at 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 at architextus.com
MG
Marc van Grootelin reply to France Baril, 13 Mar 2015, 20:0813 Mar 2015 20:01 #
Hi France, If you really need multi-branching if then else the language doesnt require increasing indentation.
  if (cond1)
  then expr1
  else if (cond2)
  then expr2
  else expr3
In my opinion this is just as good as using switch, i've seen examples like this even in the spec. Of course readability suffers if there's a lot going on in the expressions such as complete flwor expressions but that's just a matter of breaking up the code in smaller (re-usable) pieces/functions. Breaking up / refactoring your logic to avoid massive if then else or switch constructs is advisable anyway. But I don't know how your code looks so I cannot say. hth --Marc
FB
France Barilin reply to Christian Grün, 13 Mar 2015, 12:5213 Mar 2015 20:08 #
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!
Quoted text · Christian Grün · 108 lines
On Fri, Mar 13, 2015 at 4:52 AM, Christian Grün <christian.gruen at 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 at 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 at 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 at architextus.com >
-- France Baril Architecte documentaire / Documentation architect france.baril at architextus.com
FB
France Barilin reply to Marc van Grootel, 13 Mar 2015, 20:0114 Mar 2015 07:56 #
Hmmm! Sometimes, we get stuck in the simplest things. I see you can actually follow the pattern pretty well without indent. I tend to do everything in small functions the only time I get more then a function call is when I need different calls based on ancestors, and that's also pretty short. Thank you Mark.
Quoted text · Marc van Grootel · 25 lines
On Fri, Mar 13, 2015 at 12:01 PM, Marc van Grootel < marc.van.grootel at gmail.com> wrote: > Hi France, > > If you really need multi-branching if then else the language doesnt > require increasing indentation. > > if (cond1) > then expr1 > else if (cond2) > then expr2 > else expr3 > > In my opinion this is just as good as using switch, i've seen examples > like this even in the spec. Of course readability suffers if there's a lot > going on in the expressions such as complete flwor expressions but that's > just a matter of breaking up the code in smaller (re-usable) > pieces/functions. > > Breaking up / refactoring your logic to avoid massive if then else or > switch constructs is advisable anyway. But I don't know how your code looks > so I cannot say. > > hth > --Marc
-- France Baril Architecte documentaire / Documentation architect france.baril at architextus.com

⚡Generated with XQuery