Discussion:
[xquery-talk] Help understanding typeswitch-based Identity Transform
Bridger Dyson-Smith
2018-02-15 17:04:11 UTC
Permalink
Hi list --

I'm trying to get a better understanding of identity transforms in Xquery
and I don't understand the finer points of the approaches for dealing with
specific elements.

I've finally to become used to the XSLT approach, using a matching template
to process `field[@name='first']`, e.g. would someone be willing to shine
some light on different methods for dealing with this?

Thanks very much for your time and trouble.
Best,
Bridger

Example:

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)

Output should look something like:

<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>
Joe Wicentowski
2018-02-16 16:01:59 UTC
Permalink
Hi Bridger,

To be able to treat your field elements differently based on their @name,
you'd have to add some conditional logic to the return clause of your
"element(field)" case. You could place this logic right in local:dispatch,
or you could create a new function, like local:field, which would take a
field element and check the value of @name.

You're right that typeswitch is limited to relatively simple sequence
patterns, and doesn't accommodate full XPath expressions. Typically,
typeswitch performs the high level node type or element name check, and
then delegates more complex logic to functions.

Joe
Post by Bridger Dyson-Smith
Hi list --
I'm trying to get a better understanding of identity transforms in Xquery
and I don't understand the finer points of the approaches for dealing with
specific elements.
I've finally to become used to the XSLT approach, using a matching
to shine some light on different methods for dealing with this?
Thanks very much for your time and trouble.
Best,
Bridger
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)
<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>
_______________________________________________
http://x-query.com/mailman/listinfo/talk
Bridger Dyson-Smith
2018-02-16 16:12:16 UTC
Permalink
Hi Joe,

thanks for the response. I'll explore moving the XPath checks and see where
that gets me.

Appreciatively,
Bridger
Post by Joe Wicentowski
Hi Bridger,
you'd have to add some conditional logic to the return clause of your
"element(field)" case. You could place this logic right in local:dispatch,
or you could create a new function, like local:field, which would take a
You're right that typeswitch is limited to relatively simple sequence
patterns, and doesn't accommodate full XPath expressions. Typically,
typeswitch performs the high level node type or element name check, and
then delegates more complex logic to functions.
Joe
On Thu, Feb 15, 2018 at 12:04 PM, Bridger Dyson-Smith <
Post by Bridger Dyson-Smith
Hi list --
I'm trying to get a better understanding of identity transforms in Xquery
and I don't understand the finer points of the approaches for dealing with
specific elements.
I've finally to become used to the XSLT approach, using a matching
to shine some light on different methods for dealing with this?
Thanks very much for your time and trouble.
Best,
Bridger
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)
<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>
_______________________________________________
http://x-query.com/mailman/listinfo/talk
Loading...