- The problem:
The standard method of updating a record is to fetch the original
record, then build a new record as a merge between the unmodified fields
taken from the original and the new modified fields, then update the
database by substituting the old record with the new one.
This works fine until you change the record structure. If you forgot to
change the code, even if you updated your database, you will be
updating records with a version that is obsolete (and all this
when you thought that your XML database was immune from this type of
problems).
- The solution:
Write a function that correctly update an existing record
by automatically copying all the elements from the original record
but substituting the specified ones.
- The original record:
<record><name>Luigi</name><address>somewhere over the rainbow</address><phone>123-4567</phone><e-mail>luigi@somewhere.over.ra</e-mail><notes>this is a $dollar</notes></record>
- The changes:
(
<name>Mario</name>
<e-mail>mario@its.me.mario.com</e-mail>
<phone>555-1212</phone>
)
- The updated record:
<record><name>Mario</name><address>somewhere over the rainbow</address><phone>555-1212</phone><e-mail>mario@its.me.mario.com</e-mail><notes>this is a $dollar</notes></record>
- The "update" function:
define function update-element($root, $changes) {
element { node-name($root) }
{
$root/@*,
for $ele in $root/*
let $new := $changes[node-name(.) = node-name($ele)]
return if (empty($new)) then $ele else $new
}
}
- The disclaimer:
The previous function is very simple. It only substitutes top level
elements with the ones specified in the $changes list. And it
doesn't substitute attributes
But you get the idea and you can make it as complex as you want.
(of course it would be much better if there was at extension function
that would do this the right way)