TLDR : I need to move an element as first child of another using XQuery
I'm working on an XML TEI critical edition (an alignment of three different versions of a text) and need to update my document to show the base version of the text. At the moment, my edition looks like:
<app corresp="#orth">
<rdg wit="#atw">feust</rdg>
<rdg wit="#brl">fust</rdg>
<rdg wit="#brn">fut</rdg>
</app>
As you can see, the variations are signalled within an <app>
element in which the versions of the text are encoded each in an <rdg>
element.
What I need to do : transform the <rdg>
element that has an attibute @wit="#brl"
into a <lem>
element, and move it as the first of the three elements in the <app>
. So basically, transform the above example into:
<app corresp="#orth">
<lem wit="#brl">fust</lem>
<rdg wit="#atw">feust</rdg>
<rdg wit="#brn">fut</rdg>
</app>
The document is pretty long, so I thought of automating the process using XQuery. However, I'm having troubles.
So far, I've managed to transform the <rdg>
into a <lem>
, using this query :
let $doc := db:open("#...")
let $brl := $rdg[contains(@wit, "#brl")]
for $el in $brl
return rename node $el as "lem"
Now, I need to move the <lem>
as first child of <app>
. That's the part with which I'm having trouble. All I've managed to do so far is to copy the <lem>
as first child of <app>
, but by only returning the <app>
elements and not the entire document. Here's the query I used:
let $doc := db:open("#...")
let $app := $doc//app
for $el in $app
return
copy $target := $el
modify (
insert node $target/lem as first into $target
)
return $cible
The following steps I need to achieve are:
- Managing to copy the
<lem>
as first child of<app>
, but with returning the whole document (I tried to do this with anif...else
, but with no success. - Deleting the
<lem>
elements that are not the first children of an<app>
(the above request duplicates the<lem>
, so that means we have two<lem>
per<app>
).
I don't have a lot of experience with XQuery, appart from a 10 hours of class, so a little bit of help would be highly appreciated ! Thanks so much in advance.
EDIT
Christian's answer (see code below) works, but only returns the modified elements, not the entire updated document:
return $app update {
delete node ./lem,
insert node ./lem as first into .
}
I would need to update the whole document with the updated elements. I haven't managed to export the document with the updates. Another thing I've tried is:
- iterating through the whole document
- if the elements are
<app>
, modifying and returning them - else, returning the unchanged elements:
for $el in $doc//*
if ($el = $app)
return $app update {
delete node ./lem,
insert node ./lem as first into .
}
else return $el
The above transaction has an obvious mistake I can't seem to get rid of : you can't just return an unchanged element in an else
statement. The question now is: how can I update the whole document with the updated <app>
?