Merge XML fragments into a composite document
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
xquery version "3.1"; | |
(:~ Merge XML fragments with the same root node into a composite document. | |
: Based on a question from the exist-open mailing list. | |
: | |
: @see https://markmail.org/message/gdrhscaobyya44we | |
:) | |
(: Compare the fragment to the composite document. If the node names match, | |
: then recursively descend into child nodes to continue the comparison; | |
: if the fragment does not match, then deposit the non-matching fragment | |
: node into the composite. :) | |
declare function local:merge-fragment($fragment-node as node(), $composite-node as node()) { | |
if ($fragment-node/node-name() eq $composite-node/node-name()) then | |
element { $fragment-node/node-name() } { local:merge-fragment($fragment-node/node(), $composite-node/node()) } | |
else | |
($fragment-node, $composite-node) | |
}; | |
(: Pass each fragment to the merge-fragment function until we've merged them | |
: all into the composite document. :) | |
declare function local:merge-fragments($fragments as node()*, $composite as node()) { | |
if (exists($fragments)) then | |
let $fragment-to-merge := head($fragments) | |
let $updated-composite := local:merge-fragment($fragment-to-merge, $composite) | |
let $remaining-fragments := tail($fragments) | |
return | |
local:merge-fragments($remaining-fragments, $updated-composite) | |
else | |
$composite | |
}; | |
(: Check to make sure the fragments share the same root element, | |
: since otherwise they can't be merged. If they are mergeable, | |
: treat the 1st fragment as the initial "composite" that all | |
: other fragments are merged into. :) | |
declare function local:merge-fragments($fragments as node()*) { | |
if (count(distinct-values($fragments/node-name())) gt 1) then | |
"can't merge these elements - they don't have the same root element" | |
else | |
let $initial-composite := head($fragments) | |
let $initial-fragments := tail($fragments) | |
return | |
local:merge-fragments($initial-fragments, $initial-composite) | |
}; | |
let $var1 := <fileDesc> | |
<sourceDesc> | |
<msDesc> | |
<physDesc> | |
<objectDesc form=""/> | |
</physDesc> | |
</msDesc> | |
</sourceDesc> | |
</fileDesc> | |
let $var2 := <fileDesc> | |
<sourceDesc> | |
<msDesc> | |
<msIdentifier> | |
<idno/> | |
</msIdentifier> | |
</msDesc> | |
</sourceDesc> | |
</fileDesc> | |
let $var3 := <fileDesc> | |
<titleStmt> | |
<title/> | |
</titleStmt> | |
</fileDesc> | |
return | |
local:merge-fragments(($var1, $var2, $var3)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<fileDesc> | |
<titleStmt> | |
<title/> | |
</titleStmt> | |
<sourceDesc> | |
<msDesc> | |
<msIdentifier> | |
<idno/> | |
</msIdentifier> | |
<physDesc> | |
<objectDesc form=""/> | |
</physDesc> | |
</msDesc> | |
</sourceDesc> | |
</fileDesc> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment