Hi list --
apologies if you've seen this message in other mailing lists or IRC. This isn't BaseX-specific, and so I hope that's not troublesome.
I'm trying to develop a better understanding of how to leverage the identity transform pattern (or whatever the best term would be) in XQuery. Based on some web searching, typeswitch seemed to be the recommended method; e.g. [1]. But I would run into problems with using `case element($node[@name='first') return local:do-something-specific-with-this($node)`. After some chat with Liam on IRC yesterday, he gave me the idea of trying a plain(er) `switch` but I couldn't quite work out the comparison of a local-name($node) to the atomized value, especially when I needed to evaluted an XPath expression as part of the `case`. Eventually I settled on if-then-else; e.g. [2]. It feels a little unwieldy.
Note that in my (typical) usecases I'm transforming entire documents, see [3] for example output.
I can't help but wonder though: it there a better way to handle this? Am I missing something obvious with the typeswitch method? I started with XSLT and I feel like maybe I'm doing something wrong :).
Thanks for any suggestions or pointers you can offer. Best, Bridger
PS Again, hopefully this isn't too off-topic for the list.
(: [1] identity transform with typeswitch :)
declare variable $input := <docs> <doc> <title>ABC: The Alphabet</title> <author>Some Person</author> <fields> <field name="first">First Field</field> <field name="second">Second Field</field> </fields> </doc> </docs>;
declare function local:passthru( $node as node()* ){ local:dispatch($node/node()) };
declare function local:dispatch( $nodes as node()* ) as item()* { for $node in $nodes return typeswitch($node) case text() return $node case element(docs) return local:passthru($node) case element(doc) return local:docf($node) case element(title) return local:title($node) case element(author) return local:author($node) case element(fields) return local:passthru($node) case element(field) return () (:return empty sequence:) default return local:passthru($node) };
declare function local:docf($node) { <new>{local:dispatch($node/node())}</new> };
declare function local:title($node) { <new-title>{local:dispatch($node/node())}</new-title> };
declare function local:author($node) { <new-author>{local:dispatch($node/node())}</new-author> };
local:dispatch($input)
(: [2] identity transform with if-then-else :)
declare function local:dispatch( $nodes as node()* ) as item()* { for $node in $nodes return( if ($node instance of text()) then $node/data() else (), if (fn:local-name($node) = 'docs') then local:passthru($node) else (), if (fn:local-name($node) = 'doc') then local:docf($node) else (), if (fn:local-name($node) = 'title') then local:title($node) else (), if (fn:local-name($node) = 'author') then local:author($node) else (), if (fn:local-name($node) = 'fields') then local:passthru($node) else (), if (fn:local-name($node) = 'field' and $node/@name='first') then local:field-1($node) else (), if (fn:local-name($node) = 'field' and $node/@name='second') then local:field-2($node) else () ) };
(: [3] sample output :) <new> <new-title>ABC: The Alphabet</new-title> <new-author>Some Person</new-author> <new-subject>First Field</new-subject> <new-section> <new-entry>Second Field</new-entry> </new-section> </new>