Skip to content

Instantly share code, notes, and snippets.

@line-o
Last active July 2, 2024 14:08
Show Gist options
  • Save line-o/8bd25e66a51049937645e385ddae730f to your computer and use it in GitHub Desktop.
Save line-o/8bd25e66a51049937645e385ddae730f to your computer and use it in GitHub Desktop.
Preserve namespaces when traversing trees (see also the clean solution that works in Saxon https://xqueryfiddle.liberty-development.net/6qVSgfh/6)
xquery version "3.1";
module namespace emt="//external-module-test";
declare function emt:transform($node as node()) as node()+ {
typeswitch ($node)
case document-node() return document { emt:transform($node/element()) }
case attribute(xml:id) return (
attribute old-id { $node/string() },
attribute xml:id { "s" || $node }
)
case element() return element { node-name($node) } {
(: in a library module we can use the clean version of the namespace construction :)
in-scope-prefixes($node) ! namespace { . } { namespace-uri-for-prefix(., $node) },
$node/(@*, *) ! emt:transform(.)
}
default return $node
};
<TEI xmlns="http://www.tei-c.org/ns/1.0" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:svg="http://www.w3.org/2000/svg" xmlns:math="http://www.w3.org/1998/Math/MathML">
<div data="something" old-id="0ld" xml:id="s0ld">
<a xi:include="something"/>
<svg:svg/>
<math:math/>
</div>
</TEI>
xquery version "3.1";
import module namespace emt="//external-module-test" at "emt.xq";
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:method 'xml';
declare option output:indent 'yes';
declare function local:transform($node as node()) as node()+ {
typeswitch ($node)
case document-node() return document { local:transform($node/element()) }
case attribute(xml:id) return (
attribute old-id { $node/string() },
attribute xml:id { "s" || $node }
)
case element() return element { node-name($node) } {
(: in a main module we need to workaround a quirk in eXistdb to construct namespaces :)
("", in-scope-prefixes($node)[. castable as xs:NCName])
! namespace { . } { namespace-uri-for-prefix(., $node) },
$node/(@*, *) ! local:transform(.)
}
default return $node
};
declare variable $testdata :=
<TEI
xmlns="http://www.tei-c.org/ns/1.0"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:math="http://www.w3.org/1998/Math/MathML"
>
<div data="something" xml:id="0ld">
<a xi:include="something" ></a>
<svg:svg />
<math:math />
</div>
</TEI>
;
emt:transform($testdata),
local:transform($testdata)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment