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> ?