<?xml version="1.0" encoding="UTF-8"?>

<!--DOCTYPE book SYSTEM "frameworks/docbook/4.2/dtd/docbookx.dtd"-->
<book xmlns:ci="http://apache.org/cocoon/include/1.0">
    <bookinfo>
        <graphic fileref="logo.jpg"/>
        <productname>Open Source Native XML Database</productname>
        <title>XQuery Update Extensions</title>
        <author>
            <firstname>Wolfgang M.</firstname>
            <surname>Meier</surname>
        </author>
    </bookinfo>
    <ci:include src="sidebar.xml"/>
    <chapter>
        <title>XQuery Update Extensions</title>
        <para>Previous versions of eXist already offered some functions to
            execute XUpdate queries from within XQuery. However, this approach
            had its limitations, mainly due to the lack of integration
            between the XUpdate language and XQuery. XUpdate operations are
            specified in XML and the XUpdate processor uses its own instance of
            the query engine. To forward information from the XQuery to the
            XUpdate, one had to dynamically construct an XUpdate XML fragment,
            passing the required XPath expressions as strings.</para>
        <para>We thus provide an extension to XQuery, which maps each of the
            XUpdate instructions to a corresponding XQuery expression. Until the
            W3C working group starts its work on an official update 
            specification, the basic syntax follows the proposal by Patrick Lehti.</para>
        <important>
            <para>The XQuery update extension has been designed to simplify updates on 
                <emphasis>persistent</emphasis> documents stored in the database. However, it is 
                not suitable for updating temporary document fragments constructed within the XQuery, 
                i.e. you can't use it to modify the results returned by a query. For example, the following
                query has no visible effect because it operates on an in-memory fragment:
            </para>
            
            <synopsis><![CDATA[let $doc := <root><a/></root>
return (update insert <b/> into $doc/a, $doc)]]></synopsis>
            
            <para>The query just ignores the update and returns the constructed root element (it would 
                probably be less confusing if the query would just throw an exception. We may have to change 
                that ...)</para>
        </important>
        <para>All update statements start with the keyword "update", followed by
            an update action. Available actions are: "insert", "delete", "replace", 
            "value" and "rename". The return type of the expression is <option>empty()</option>.
        </para>
        <para>An update statement may occur at any position within the XQuery main 
            code or a function body. When using an update within the return
            clause of a FLWOR expression, it should be clear that one should not 
            delete or replace nodes that are still being used by enclosing code. A delete 
            or replace will be processed immediately, and
            the deleted or replaced node will no longer be available. For example, the
            following expression throws the db into an inconsistent state if //address
            returns more than one node:</para>
        <example>
            <title>Bad Update</title>
            <programlisting><![CDATA[
for $address in //address
return
    update delete //address]]></programlisting>
        </example>
        
        <para>However, an expression like the following is save as it only modifies the 
            current iteration variable:</para>
        <example>
            <title>Complex Update</title>
            <programlisting><![CDATA[
for $address in //address
return
    (: Move lname and fname into a new name element :)
    update replace $address with
        <address>
            <name>
                <family>{$address/lname/text()}</family>
                <given>{$address/fname/text()}</given>
            </name>
            {$address/city, $address/email}
        </address>]]></programlisting>
        </example>
        
        <section>
            <title>Insert</title>
            <synopsis>update insert expr ( into | following | preceding )
                exprSingle</synopsis>
            <para>Inserts the content sequence specified in expr into the
                element node passed via exprSingle. exprSingle and expr should evaluate to a node
                set. If exprSingle contains more than one element node, the
                modification will be applied to each of the nodes. The
                position of the insertion is determined by the keywords "into",
                "following" or "preceding":</para>
            <variablelist>
                <varlistentry>
                    <term>into</term>
                    <listitem>
                        <para>The content is appended after the last child node
                            of the specified elements.</para>
                    </listitem>
                </varlistentry>
                <varlistentry>
                    <term>following</term>
                    <listitem>
                        <para>The content is inserted immediately after the node specified
                            in exprSingle.</para></listitem>
                </varlistentry>
                <varlistentry>
                    <term>preceding</term>
                    <listitem>The content is inserted before the node specified
                        in exprSingle.</listitem>
                </varlistentry>
            </variablelist>
            <example>
                <title>Insert Example</title>
<programlisting><![CDATA[
update insert <email type="office">andrew@gmail.com</email> into //address[fname="Andrew"]
]]></programlisting>
            </example>
        </section>
        <section>
            <title>Replace</title>
            <synopsis>update replace expr with exprSingle</synopsis>
            <para>Replaces the nodes returned by expr with the nodes in
                exprSingle. expr may evaluate to a single element, attribute or
                text node. If it is an element, exprSingle should contain a
                single element node as well. If it is an attribute or text node, the
                value of the attribute or the text node is set to the concatenated string values of all
                nodes in expr.</para>
            <example>
                <title>Replace Example</title>
                <programlisting><![CDATA[update replace //fname[. = "Andrew"] with <fname>Andy</fname>]]></programlisting>
                
            </example>
        </section>
        <section>
            <title>Value</title>
            <synopsis>update value expr with exprSingle</synopsis>
            <para>Updates the content of all nodes in expr with the items in
                exprSingle. If expr is an attribute or text node, its value will
                be set to the concatenated string value of all items in
                exprSingle.</para>
        </section>
        <section>
            <title>Delete</title>
            <synopsis>update delete expr</synopsis>
            <para>Removes all nodes in expr from their document.</para>
            <example>
                <title>Delete Example</title>
                <programlisting><![CDATA[for $city in //address/city return update delete $city]]></programlisting>
            </example>
        </section>
        <section>
            <title>Rename</title>
            <synopsis>update rename expr as exprSingle</synopsis>
            <para>Renames the nodes in expr using the string value of the first
                item in exprSingle as the new name of the node. expr should
                evaluate to a set of elements or attributes.</para> 
        </section>
    </chapter>
</book>