The Problem of Invisible Updates

The fact that updates are applied only at the end of a script execution has two consequences on programming, one disturbing, one pleasant:

  • The disturbing consequence is that you don't see your updates until the end, therefore you cannot build on your changes to make other changes.

    An example: suppose you have elements named PERSON. Inside a PERSON there can be a list of BID elements (representing bids made by this person), and you want the BID elements to be wrapped in a BIDS element. But initially the PERSON has no BIDS child.

    Initially:

    <PERSON id="p0103">
      <NAME>Jane</NAME>
    </PERSON>

    We want to insert <BID id="b0022">data</BID> to obtain:

    <PERSON id="p0103">
      <NAME>Jane</NAME>
      <BIDS>
         <BID id="b0022">data</BID>
      <BIDS>
    </PERSON>

    Classically, for example using the DOM, we would proceed in two steps:

    1. If there is no BIDS element inside PERSON, then create one

    2. then insert the BID element inside the BIDS element

    In XQuery Update this would (incorrectly) be written like this:

    declare updating function insert-bid($person, $bid)
    {
      if(empty($person/BIDS))
        then insert node <BIDS/> into $person
        else (),
      insert node $bid as last into $person/BIDS
    }

    Don't try that: it won't work! Why?
    Because the BIDS element will be created only at the very end, therefore the instruction insert ... as last into $person/BIDS will not find any node matching $person/BIDS, hence throw an execution error.

    So what is a correct way of doing ? We need a self-sufficient solution for each of the two cases:

    declare updating function insert-bid($person, $bid)
    {
     if(empty($person/BIDS))
       then insert node <BIDS>{$bids}</BIDS> into $person
       else insert node $bid as last into $person/BIDS
    }
  • The pleasant consequence is that the document(s) on which you are working are stable during execution of your script. You can rest assured that you are not sawing the branch you are sitting on. For example you can quietly write:

    for $x in collection(...)//X
    return delete node $x

    This is perfectly predictable and won't stop prematurely. Or you can replicate an element after itself without risking looping forever:

    for $x in collection(...)//X
    return insert node $x after $x

Copyright © 2010 - 2023 Emakin. All rights reserved.