<?xml version="1.0" encoding="UTF-8"?>
<!-- $Id: beginners-guide-to-xrx-v4.xml 17458 2012-11-01 08:24:14Z jenspetersen $ --><book xmlns:xlink="http://www.w3.org/1999/xlink"><bookinfo><productname>eXist-db – Open Source Native XML Database</productname><title>A Beginners Guide to XRX with eXist</title><subtitle>A step-by-step guide for beginners to creating your first XRX
            application.</subtitle><author><personname><firstname>Dan</firstname><surname>McCreary</surname></personname><email>dan at syntactica.com</email></author><author><personname><firstname>Henry</firstname><surname>Neils</surname></personname><email>henry at syntactica.com</email></author><author><personname><firstname>Loren</firstname><surname>Cahlander</surname></personname><email>loren at syntactica.com</email></author><author><personname><firstname>Joe</firstname><surname>Wicentowski</surname></personname><email>joewiz at gmail.com</email></author><revhistory><revision><revnumber>1</revnumber><date>2010-03-23</date><author><personname><firstname>Dan</firstname><surname>McCreary</surname></personname></author><revdescription><para>Initial Draft</para></revdescription></revision><revision><revnumber>2</revnumber><date>2010-03-30</date><author><personname><firstname>Dan</firstname><surname>McCreary</surname></personname></author><revdescription><para>Cleaned up spelling and added more detail. Added a figure for edit
                        bindings.</para></revdescription></revision><revision><revnumber>3</revnumber><date>2010-03-30</date><author><personname><firstname>Joe</firstname><surname>Wicentowski</surname></personname></author><revdescription><para>Edited for clarity and style.</para></revdescription></revision><revision><revnumber>4</revnumber><date>2010-04-1</date><author><personname><firstname>Dan</firstname><surname>McCreary</surname></personname></author><revdescription><para>Fixed typos and modified sections for clairity.</para></revdescription></revision></revhistory></bookinfo><chapter><section><title>Introduction</title><para>The following is a Beginner's Guide for creating a new XRX application with the
                eXist application server. It is intended for people who are new to eXist and are
                interested in building their first web applications. This guide demonstrates the
                minimal code necessary to create applications that perform "CRUDS" operations. These
                operations are: <emphasis role="bold">C</emphasis>reate, <emphasis role="bold">R</emphasis>ead (or view), <emphasis role="bold">U</emphasis>pdate, <emphasis role="bold">D</emphasis>elete and <emphasis role="bold">S</emphasis>earch.
                Creating your first XRX application can be somewhat tricky, since there are several
                structures that need to be "wired" together correctly for the CRUDS components to
                work correctly. This example tries to use as little code as possible and yet still
                cover many of the key components of a fully functional XRX web application.</para><section><title>Intended Audience</title><para>Creating a new web application from scratch is a core skill that is necessary
                    to understand the power of the XRX web application architecture. Our experience
                    has shown that once users get an understanding of how XRX applications are
                    constructed, they can quickly become productive building new web applications.
                    They also have a much better understanding of the complex portions of the XRX
                    application and why these portions are usually automated in XRX
                    frameworks.</para><para>This document is designed for new eXist-db users who would like to create
                    their first XRX application. For this process we assume that you have a basic
                    understanding of XML and understand concepts such as XML elements and XPath
                    expressions. The user should also be somewhat familiar with very basic HTML
                    markup, including the structure of an XHTML file and use of HTML lists and HTML
                    tables. We will also be describing how XQuery is used to create a listing of
                    items and viewing an individual item. Users should review the basic structure of
                    an XQuery FLOWR expression (for, let, order by, where, and return) and basic
                    XQuery syntax. Familiarity with the fundamentals of XForms is helpful but this
                    guide will explain each of the XForms elements used in the example.</para><para>Please note that there are several easy-to-use drag-and-drop GUI tools
                    available that can create XForms, and there are systems that can also
                    automatically create a fully functional XRX application directly from an XML
                    Schema. But using these tools and frameworks hide much of the inner workings of
                    an XRX application. So this tutorial is for those that want to have a clear
                    understanding of how XRX systems work.</para></section><section><title>Getting Started</title><para>To use this guide you will need to have following tools in place: <orderedlist><listitem><para><emphasis role="bold">eXist-db</emphasis> You will need to have a
                                version of the <ulink url="http://exist-db.org">eXist</ulink> XML
                                application server running on your local system. By default eXist
                                runs on port 8080 so that when you set your web browser to
                                http://localhost:8080/exist/ you should see the eXist homepage come
                                up. You can also run this tutorial on any remote eXist server. If
                                you are doing this, you must replace the word "localhost" with the
                                name of your remote server. Make sure that you take into account the
                                port number; it might not be 8080, or it may be missing, which
                                implies that the port number is the default port 80.</para></listitem><listitem><para><emphasis role="bold">XML and XQuery Editor</emphasis> You will need
                                some tool to edit XML and XQuery files. We strongly encourage you to
                                use a tool such as the oXygen XML Editor, since this tool has
                                special additions to make editing XML and XQuery files easy. Simple
                                text editors such as Microsoft Notepad <!--delete or add more exampes -->will work but will not give
                                you immediate feedback when there are syntax errors in your files.
                                The XML and XQuery syntax highlighting feature of editors like
                                oXygen is very useful when you are first learning an new programming
                                system. Since there are 30-day free trials of many tools we strongly
                                encourage new users to use good XML editors.</para></listitem><listitem><para><emphasis role="bold">File Uploader</emphasis> You will need some
                                tool to transfer your files directly to eXist. Tools like oXygen can
                                save directly to the eXist database, or you can also use a WebDAV
                                client to copy the files. There are also web uploader tools in the
                                eXist admin area and there are custom versions that also allow you
                                to upload and expand an entire ZIP file within the database. <!--don't understand last part of last sentence--> As a
                                final option, you can also use the eXist-db Java console to upload
                                files.</para></listitem><listitem><para><emphasis role="bold">XForms</emphasis> You will need some XForms
                                client libraries. This example will use the XSLTForms client which
                                is usually installed in /db/xforms/xsltforms. <!--xsltforms is usually installed in webapp/xforms; if article assumes another location, it should specify the procedure -->You do not have to use
                                libraries that are in the eXist-db database <!--unclear: does this refer to xsltforms in webapp/xforms? -->but this is sometimes
                                preferable.</para></listitem></orderedlist></para></section><section><title>Terms and Concepts Used</title><para>This example will use the following terms and concepts:</para><para><termdef><emphasis role="bold">XRX</emphasis></termdef>is the name of the web application architecture that we are
                    introducing in this guide. The term XRX comes from the combination of XForms,
                    REST, and XQuery. <!--who has coined this expression? -->XForms are used in the client (web browser), REST is the
                    interface between the client and the server, and XQuery is the server language.
                    Two of the most significant advantages of XRX over other architectures are: (1)
                    it does not require users to translate data into Java or .Net objects, and (2)
                    it does not require users to "shred" documents into rows of a relational
                    database.</para><para><termdef><emphasis role="bold">XForms</emphasis></termdef> is a W3C standard consisting of set of around 25 XML tags that are
                    used to define the structure of a web from. XForms is much more advanced than
                    traditional HTML forms, but can appear intimidating to the first time user.
                    However, most simple forms need only a few control types, and these can be
                    quickly learned. XForms bind user interface controls to each leaf element in an
                    XML instance. XForms stores the data in a model element in the HTML HEAD tag and
                    then binds the leaf elements in the model to web input controls. </para><para><termdef><emphasis role="bold">XQuery</emphasis></termdef> is a W3C standard query language for selecting and transforming XML
                    structures. If you don't have programming experience, XQuery is not hard to pick
                    up. If you do have programming experience, XQuery is a little different than
                    other languages you may have used in the past. It is a "functional" programming
                    language that makes it very easy to create robust server-side programs --
                    programs that do not have many of the "side-effects" of other languages. It is
                    similar to the SQL language in some ways, but it is specifically designed for
                    XML structures. Paired with an XML database like eXist, XQuery is an ideal
                    language for creating web applications. eXist's highly efficient indexing
                    makes full text searches and other queries very fast, even when working
                    with gigabytes of XML data. </para><sidebar><para><emphasis role="bold">Note for New XQuery Users</emphasis>. There are some
                        things that are very different in XQuery that you should be aware of. In
                        general, all XQuery variables are <emphasis role="italic">immutable</emphasis>, meaning that they are designed to be set once but
                        never changed. So functions like let $x := $x + 1 within loops will not
                        increment like in procedural languges. There are also restrictions on what
                        can be done inside FLOWR statements. We will illustrate these in examples in
                        future Beginner's Guides.</para>
                <!--this note can probably be left out. reference to future articles is not good--></sidebar><para><termdef><emphasis role="bold">REST</emphasis></termdef> is at the heart of the architecture of the World Wide Web. We use
                    the "RESTful" approach to passing information around in our XRX application by
                    simply placing parameters at the end of a URL. For example, to pass a query
                    keyword to a our XRX application search service, our form appends the parameter
                    q=myword to the URL: search.xq?q=myword. If you have ever used a SOAP
                    architecture, REST is a breath of fresh air. No complex SOAP interface testing
                    tools are required. All you need to test your web services is a web browser. For
                    example, the home page of the test application under the default configuration
                    will be http://localhost:8080/exist/<emphasis role="bold">rest</emphasis>/db/apps/term/index.html. Note that the word "rest" comes after
                    the /exist/ and before the /db/.</para><para>Several additional terms and concepts are helpful in understanding the XRX
                    approach:</para><para><termdef><emphasis role="bold">WebDAV</emphasis></termdef> is a protocol for transfering files, and we use eXist's WebDAV
                    interface to move files to and from eXist and to list files in eXist
                    collections. If you want to add a folder to eXist you can do this through the
                    WebDAV interface. When you use oXygen or other editors you will also use the
                    WebDAV interface. To open a file through the WebDAV interface you might open
                        http://localhost:8080/exist/<emphasis role="bold">webdav</emphasis>/db/apps/term/</para><para><termdef><emphasis role="bold">Model-View Bindings</emphasis></termdef> is the term we use to describe how user interface elements (controls)
                    within a form are associated with leaf-level elements within the XForms model.
                    This is similar to the Model-View-Controller (MVC) architecture in other
                    systems, but in the case of XForms event controls are part of the views. By
                    using XPath statements in the <emphasis role="bold">ref</emphasis> attributes
                    for user interface controls, the browser constructs a dependency graph to keep
                    the model and views in sync. This makes forms development much easier since the
                    form developer never needs to manually move data between the model and the
                    views.</para><para><termdef><emphasis role="bold">Convention over Configuration</emphasis></termdef> is a common practice among modern web application frameworks like XRX
                    of using conventions such as standardized collection and file names, to reduce
                    the amount of configuration and thereby reduce the complexity and time required
                    to prototype and complete applications. Of course, users have the ability to
                    change these conventions, but they then take responsiblity for maintaining their
                    own adaptations or separate frameworks. </para></section></section><section><title>Collection and File Conventions</title><para>The first convention of XRX applications involves the data collections and files
                that will structure our application. Although you do not have to use the collection
                conventions used in this example, you will find that frameworks that use this
                convention will be much easier to build and maintain. </para><para>Here are the standards we strongly recommend you use for your first
                application:</para><orderedlist><listitem><para><emphasis role="bold">Apps</emphasis> All XRX applications should be grouped
                        in a single collection. For example <emphasis role="bold">/db/apps</emphasis> or <emphasis role="bold">/db/org/mycompany/apps</emphasis>. The exact location of the apps
                        collection in the databases is not relevant, but all apps should be stored
                        together in a collection called apps.</para></listitem><listitem><para><emphasis role="bold">App</emphasis> Each XRX application should be grouped
                        in a collection. This collection name should reflect the function of the
                        application. For example, our business term application might be stored in
                        the <emphasis role="bold">/db/apps/terms</emphasis> collection. The
                        convention is to use the plural ("terms" rather than "term") for the primary
                        kind of content being stored in the app.</para></listitem><listitem><para><emphasis role="bold">Data</emphasis> Each XRX application should store its
                        data in a separate data collection. For example, our term manager application
                        will store all the data in /db/apps/terms/data. In this example the first
                        term will be stored in the file <emphasis role="bold">1.xml</emphasis> and
                        the second in the file <emphasis role="bold">2.xml</emphasis>, etc. When the
                        user saves new terms, we can increment a counter to add a new term.</para></listitem><listitem><para><emphasis role="bold">Views</emphasis> Each XRX application should store
                        read-only views of the data in a <emphasis role="bold">views</emphasis>
                        collection. In our example, the term manager will store read-only views of
                        the data in the <emphasis role="bold">/db/term/apps/terms/views</emphasis>
                        collection. Note that views are all functions that transform but do not
                        alter the original XML data. Views collectons are usually visible to all
                        users that have read access to data. Views do not need to worry
                        about locking records to prevent missing updates. Tools that do change or
                        edit the data can be stored in another collection such as <emphasis role="bold">edit</emphasis>. This allows access control systems to limit
                        who changes or deletes data.</para></listitem><listitem><para><emphasis role="bold">Edit</emphasis> Each XRX application should store its
                        edit functions in a collection called edit. For our term manager application
                        this would be <emphasis role="bold">/db/apps/term/edit</emphasis>. Edit
                        function include saving new terms, updating terms and deleting terms. By
                        grouping all edit functions together it is easy to deny access to users that
                        do not have permission to change items and to create consistent logging
                        functions for audit trails.</para></listitem><listitem><para><emphasis role="bold">Search</emphasis> Each XRX application should store
                        its search functions in a collection called <emphasis role="bold">search</emphasis>. For our term manager application this would be
                            <emphasis role="bold">/db/apps/term/search</emphasis>. There are two
                        functions stored here. A simple HTML search form (search.html) and a RESTful
                        search (service.xq). Advanced applications sometimes combine these functions
                        into a single XQuery that generates HTML. (In addition to these two search
                        functions, an additional configuration file must be stored in the <emphasis role="bold">/db/system/config/db/apps/terms/data</emphasis> collection
                        that describes how the files are indexed for search.)</para></listitem><listitem><para><emphasis role="bold">AppInfo</emphasis> Each XRX application should store
                        information that pertains to the application in an XML file within the main
                        application collection. By convention this file is called the app-info.xml
                        file. Information such as the application name, description, author,
                        version, license, dependencies, etc. should be stored in this file. This
                        tutorial will not cover this file's structure, but you may see it in many of
                        the sample programs. This will be covered in other XRX Beginners
                        Guides. <!--reference to future articles not good.--></para></listitem></orderedlist><para>You are always free to change the names of the collection or the queries, but as
                mentioned above, you will have to take responsibility for your own frameworks and
                you may lose some of the benefits of using the common conventions. The reason for
                using a generic file name such as <emphasis role="bold">list-items.xq</emphasis>
                instead of a filename that reflects the data, such as <emphasis role="bold">list-terms.xq</emphasis>, may not be clear to you at first, but as you will see
                later, this more general file naming convention has it merits when many applications
                are being managed. </para></section><section><title>Example Data: Business Terms</title><para>In this example we will use a simple registry of business terms that might be used
                in a glossary of terms on a web site. Each term will have (1) a numeric ID, (2) a
                term name, (3) a definition, and (4) a publish-status code of "draft,"
                "under-review," or "published."</para><para>To illustrate this structure, the following is a sample XML file for one of our
                terms:
                <programlisting>&lt;term&gt;
    &lt;id&gt;1&lt;/id&gt;
    &lt;term-name&gt;Declarative Programming&lt;/term-name&gt;
    &lt;definition&gt;A style of programming that allows users to declare their requirements (what they
        want done) and leave out the details of how the function should be performed.&lt;/definition&gt;
    &lt;publish-status-code&gt;published&lt;/publish-status-code&gt;
&lt;/term&gt;</programlisting></para><para> We will create an application that will allow users to edit these terms on a
                simple form that will use a simple input field for the name, a text area for the
                definition, and a selection list for the status codes.</para></section><section><title>Views</title><para>We will create two XQuery services for our initial XRX application. The first is a
                simple XQuery that will list all the terms in our data collection that have the root
                element "term." The second is an XQuery function that shows an individual term. The
                second requires a single parameter which is the ID of the term. We will allow the
                user to drill down to see an individual term by first viewing a list of all the term
                in a collection.</para><section><title>Listing Items</title><para>Our first task will be to create a simple XQuery program that will list all
                    the terms in our collection in an HTML file. To do this we will us a simple
                    XQuery FLOWR loop that gets each of the terms in the collection in succession
                    and then converts the XML into a HTML list item using the &lt;li&gt;&lt;/li&gt;
                    tags. The convention to use in this example is the file name
                    list-items.xq.</para><para><emphasis role="bold">/db/apps/terms/views/list-items.xq:</emphasis></para><para><programlisting>xquery version "1.0";

declare option exist:serialize "method=xhtml media-type=text/html indent=yes";

&lt;html&gt;
   &lt;head&gt;
      &lt;title&gt;Glossary of Terms&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
       &lt;h1&gt;Terms&lt;/h1&gt;
       &lt;ol&gt;{
         for $term in collection('/db/apps/terms/data')/term
            let $term-name := $term/term-name/text()
            order by $term-name
            return
               &lt;li&gt;{$term-name}&lt;/li&gt;
      }&lt;/ol&gt;
    &lt;/body&gt;
&lt;/html&gt;</programlisting></para><para>This produces the following output:</para><para><inlinemediaobject><imageobject><imagedata fileref="resources/list-items-no-links.png" contentwidth="200"/></imageobject></inlinemediaobject></para><para>There are few items to note. First, note that we use the collection function to
                    specify what data is being listed. We also return only items in the data
                    collection that have term as their root element. This allows us to put other
                    data types within the data collection without disrupting this report.</para><para>Our next step is to change each of the items listed into HTML links so that we
                    can view each individual item on a separate HTML page. To do this we change the
                    &lt;li&gt;{$term-name}&lt;/li&gt; to be the following code:</para><para><programlisting>&lt;li&gt;&lt;a href="view-item.xq?id={$term/id/text()}"&gt;{$term-name}&lt;/a&gt;&lt;/li&gt;</programlisting></para><para>This produces the following output:</para><para><inlinemediaobject><imageobject><imagedata fileref="resources/list-items-links.png" contentwidth="200"/></imageobject></inlinemediaobject></para><para>This has the effect of taking each term's ID and using it as a RESTful
                    parameter, so that when a user selects this link, the link to the view-item.xq
                    query will include the ID, and the query will know which term to display. We
                    will use the same technique many times. Note that this uses a relative path to
                    the view-item.xq program. So it is important to keep both the list items and the
                    view items in the same collection for this to work correctly.</para><para>Note that this works fine as long as we have just a few hundred
                    terms. But as your collections get longer (usually above a few hundred items)
                    you will want to create a list items query that only lists the first 30 or so
                    items and then has a "next" button to get more items. This will be covered in
                    another section (see "Pagination in XQuery"). <!--reference to future article.--></para></section><section><title>Viewing an Individual Item</title><para>Now that we have a list of all the items in a collection, we are ready to drill
                    down to a specific item and see all of the information about a single item. By
                    convention this is done by an XQuery file called "view-item.xq". The item viewer
                    takes a single parameter that is the ID of the item. It has to perform a query
                    on all the items in the data collection to find only the item you are looking
                    for. This is done by adding a "predicate" or "where clause" to the query. In
                    general we prefer predicates because they are faster for eXist to process. The
                    predicate that selects our desired term appears in the square brackets in the
                    following expression:</para><para><programlisting>let $term := collection('/db/apps/terms/data')/term[id='5']</programlisting></para><para>Note that the predicate [id='5'] indicates to the system that only a term with
                    an ID of 5 should be returned. (Also note the quotes surrounding '5', which
                    indicate that we are doing simple string comparison, and not treating the ids as
                    integers.)</para><para>Our next step is to get the parameter from the URL to select the correct item.
                    This is done by using the function request:get-parameter(). We then display all
                    the elements of the term using one element per line. Here is what the source of
                    the list-item.xq file looks like: </para><para><emphasis role="bold">/db/apps/terms/views/view-item.xq</emphasis><programlisting>xquery version "1.0";

declare option exist:serialize "method=xhtml media-type=text/html indent=yes";

let $id := request:get-parameter("id", "")
let $term := collection('/db/apps/terms/data')/term[id=$id]

return
&lt;html&gt;
   &lt;head&gt;
      &lt;title&gt;Term {$term/id/text()}&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
       &lt;h1&gt;Term {$term/id/text()}&lt;/h1&gt;
       &lt;b&gt;Term ID: &lt;/b&gt; {$term/id/text()}&lt;br/&gt;
       &lt;b&gt;Term Name: &lt;/b&gt; {$term/term-name/text()}&lt;br/&gt;
       &lt;b&gt;Term Definition: &lt;/b&gt; {$term/definition/text()}&lt;br/&gt;
       &lt;b&gt;Term Status: &lt;/b&gt; {$term/publish-status-code/text()}&lt;br/&gt;
    &lt;/body&gt;
&lt;/html&gt;</programlisting></para><para>This produces the following output:</para><para><inlinemediaobject><imageobject><imagedata fileref="resources/view-item.png" contentwidth="400"/></imageobject></inlinemediaobject></para></section></section><section><title>Searching Items</title><para>There are three items that we create to support search functions. These items are the:<orderedlist><listitem><para>An HTML search form</para></listitem><listitem><para>A RESTful search service</para></listitem><listitem><para>A configuration file for defining the indexes</para></listitem></orderedlist> There are two types of indexes we will create. Structural indexes are
                configured to work with specific XML structures such as IDs. Fulltext indexes are
                used by eXist to make keyword searches very fast. These both work by indexing new
                content and optimizing the indexes for fast retrieval. Queries can run quickly and
                efficiently against the indexes rather than iterating through all files in the
                collection. In addition to the three files above, we therefore also have a script that reindexes
                the collection of terms. </para><section><title>Search Configuration File</title><para>The following is a search configuration file that we store in the collection
                        <emphasis role="bold">/db/system/config/db/apps/term/data</emphasis>.</para><para><emphasis role="bold">/db/system/config/db/apps/term/data/collection.xconf</emphasis></para><para><programlisting>&lt;collection xmlns="http://exist-db.org/collection-config/1.0"&gt;
    &lt;index&gt;
        &lt;!-- Disable the standard full text index --&gt;
        &lt;fulltext default="none" attributes="no"/&gt;
        
        &lt;!-- Range index configuration on the id attribute --&gt;
        &lt;!-- Most ids are integers but we will keep this general &lt;create qname="id" type="xs:int"/&gt; --&gt;
        &lt;create qname="id" type="xs:string"/&gt;
        
        &lt;!-- Lucene index configuration --&gt;
        
        &lt;lucene&gt;
            &lt;!-- Use the standard analyzer will ignore stopwords like 'the', 'and' --&gt;
            &lt;analyzer class="org.apache.lucene.analysis.standard.StandardAnalyzer"/&gt;
            
            &lt;!-- an index boost can be used to give matches in the
            name a higher score. This means a name match will have higher rank then
            an match in the definition. --&gt;
            &lt;text match="//term/term-name" boost="2"/&gt;
            &lt;text match="//term/definition"/&gt;
            &lt;text match="//term/publish-status-code"/&gt;
        &lt;/lucene&gt;
    &lt;/index&gt;
&lt;/collection&gt;</programlisting></para><para>This configuration file creates an index for the term ID for fast searching.
                    It also creates a Lucene fulltext index for all words in the term name, term definition and term publish-status-code.</para></section><section><title>Reindexing</title><para>After you have created or modified your configuration file, you must reindex
                    any data that you have. This can be done by pasting the following two lines into
                    the XQuery sandbox:</para><para><emphasis role="bold">Paste the following lines into the XQuery Sandbox <!--eXide-->,
                        replacing 'myadminpassword' with your eXist admin password, to reindex the
                        collection:</emphasis></para><para><programlisting>xmldb:login('/db/apps/terms/data', 'admin', 'myadminpassword'),
xmldb:reindex('/db/apps/terms/data')</programlisting></para><para>If you are not familiar with the eXist-db Sandbox <!--eXide--> you can also run the
                    following XQuery script. It is stored in the app's admin collection. The script
                    will login as the administrator and then run the reindex function on the
                    collection. It also returns the time it took to reindex the collection. For
                    collections that are under 1,000 medium sized 10K byte documents, this script
                    usually runs in a few seconds. Tools are available for larger collections to
                    schedule indexing during off hours with the eXist job scheduler.</para><para><emphasis role="bold">/db/apps/terms/admin/reindex.xq</emphasis></para><para><programlisting>xquery version "1.0";

declare option exist:serialize "method=xhtml media-type=text/html indent=yes";

let $data-collection := '/db/apps/terms/data'

let $login := xmldb:login($data-collection, 'admin', 'myadminpassword')
let $start-time := util:system-time()
let $reindex := xmldb:reindex($data-collection)
let $runtime-ms := ((util:system-time() - $start-time)
                   div xs:dayTimeDuration('PT1S'))  * 1000 

return
&lt;html&gt;
    &lt;head&gt;
       &lt;title&gt;Reindex&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
    &lt;h1&gt;Reindex&lt;/h1&gt;
    &lt;p&gt;The index for {$data-collection} was updated in 
                 {$runtime-ms} milliseconds.&lt;/p&gt;
    &lt;a href="../index.html"&gt;App Home&lt;/a&gt;
    &lt;/body&gt;
&lt;/html&gt;</programlisting></para><para><inlinemediaobject><imageobject><imagedata fileref="resources/reindex-result.png" contentwidth="400"/> <!--typos in image--></imageobject></inlinemediaobject></para></section><section><title>The Search Form</title><para>The search form is a simple HTML form with one text field input and one submit
                    button. The action of this form will use the value in the input field and send
                    the field in the q parameter to the search service.</para><para><emphasis role="bold">/db/apps/terms/tsearch/search-form.html</emphasis></para><para><programlisting>&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;Search Terms&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;h2&gt;Search Terms&lt;/h2&gt;
        &lt;form method="GET" action="search.xq"&gt;
            &lt;b&gt;Search:&lt;/b&gt;
            &lt;input name="q" type="text" value="" size="30"/&gt;
            &lt;input type="submit" value="Search"/&gt;
        &lt;/form&gt;
    &lt;/body&gt;
&lt;/html&gt;</programlisting></para><para>The following image shows a blank search screen form. To perform a search, the
                    user simply enters one or more keywords into the search form and clicks the
                    search button (or presses the enter key).</para><para><inlinemediaobject><imageobject><imagedata fileref="resources/search.png" contentwidth="300"/></imageobject></inlinemediaobject></para><para>If you put a keyword in the input field the following URL will get
                    generated:</para><para><programlisting>/db/apps/terms/search/search.xq?q=mykeyword</programlisting></para></section><section><title>The Search Service</title><para>The search service is an XQuery script that calls the fulltext search
                    function.</para><para><emphasis role="bold">/db/apps/terms/search/search.xq</emphasis></para><para><programlisting>xquery version "1.0";

declare option exist:serialize "method=xhtml media-type=text/html indent=yes";

let $data-collection := '/db/apps/terms/data'
let $q := request:get-parameter('q', "")

(: put the search results into memory using the eXist any keyword ampersand equals comparison :)
let $search-results := collection($data-collection)/term[ft:query(*, $q)]
let $count := count($search-results)

return
&lt;html&gt;
    &lt;head&gt;
       &lt;title&gt;Term Search Results&lt;/title&gt;
     &lt;/head&gt;
     &lt;body&gt;
        &lt;h3&gt;Term Search Results&lt;/h3&gt;
        &lt;p&gt;&lt;b&gt;Search results for:&lt;/b&gt;&amp;quot;{$q}&amp;quot; &lt;b&gt; In Collection: &lt;/b&gt;{$data-collection}&lt;/p&gt;
        &lt;p&gt;&lt;b&gt;Terms Found: &lt;/b&gt;{$count}&lt;/p&gt;
     &lt;ol&gt;{
           for $term in $search-results
              let $id := $term/id
              let $term-name := $term/term-name/text()
              order by upper-case($term-name)
          return
            &lt;li&gt;
               &lt;a href="../views/view-item.xq?id={$id}"&gt;{$term-name}&lt;/a&gt;
            &lt;/li&gt;
      }&lt;/ol&gt;
      &lt;a href="search-form.html"&gt;New Search&lt;/a&gt;
      &lt;a href="../index.html"&gt;App Home&lt;/a&gt;
   &lt;/body&gt;
&lt;/html&gt;</programlisting></para></section><section><title>Search Results</title><para>The form will then pass the search keyword(s) to the search service. The
                    search service will return a series of search results, with one result per hit.
                    Each result is also a link to the item-viewer service.</para><para><inlinemediaobject><imageobject><imagedata fileref="resources/search-results.png" contentwidth="300"/><!--<a href="../index.html">App Home</a> missing from image--></imageobject></inlinemediaobject></para></section></section>
        <!-- end of search section --><section><title>Editing</title><para>Editing data is the most complex portion of building an XRX application. We must
                create a form for users to edit the data, and create queries that take the form data
                and write it to the database. Because of the complexity of creating these
                interfaces, advanced XRX frameworks attempt to automate this process by generating
                all of the required files. However, this sample "business terms" app is simple
                enough for the purposes of this tutorial.</para></section><section><title>The Edit Query</title><para>The Edit query is the most complex file in this application. It must perform saves
                for new items as well as update operations. The following source code should be
                studied carefully since many of the techniques used in the form will be used in more
                complex forms. </para><section><title>Model-View-Binding</title><para>To understand how the edit.xq script works it is first important to understand
                    how the XForms standard uses Model-View-Binding to associate a user interface
                    control with an XML instance inside the model. This is illustrated in the figure
                    below.</para><para><inlinemediaobject><imageobject><imagedata fileref="resources/model-view-bindings.png" contentwidth="400"/></imageobject></inlinemediaobject></para><para> In the form, the XML data that the form allows the user to modify is loaded into an <emphasis role="bold">&lt;xs:instance&gt;</emphasis> element within the <emphasis role="bold">&lt;xf:model&gt;</emphasis>. This is specified using the
                        <emphasis role="bold">src</emphasis> attribute. Inside the body of the form,
                    each of the user interface controls (an output, input, textarea and select1
                    control) have a <emphasis role="bold">ref</emphasis> attribute. This
                    attribute contains the XPath expression of the element it corresponds to within
                    the model.</para><para><emphasis role="bold">/db/apps/terms/edit/edit.xq</emphasis></para><para>
                    <!--the namespaced css selectors no longer work--><programlisting>xquery version "1.0";

declare option exist:serialize "method=xhtml media-type=text/xml indent=yes process-xsl-pi=no";

let $new := request:get-parameter('new', '')
let $id := request:get-parameter('id', '')
let $data-collection := '/db/apps/terms/data'

(: Put in the appropriate file name.  Use new-instance.xml for new forms and get the data
   from the data collection for updates.  :)
let $file := if ($new) then 
        'new-instance.xml'
    else 
        concat('../data/', $id, '.xml')

let $form := 
&lt;html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xf="http://www.w3.org/2002/xforms" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:ev="http://www.w3.org/2001/xml-events" &gt;
    &lt;head&gt;
       &lt;title&gt;Edit Item&lt;/title&gt;
       &lt;style type="text/css"&gt;
       &lt;![CDATA[
       @namespace xf url("http://www.w3.org/2002/xforms");

       body {
           font-family: Helvetica, Ariel, Verdana, sans-serif;
       }

       .term-name .xforms-value {width: 50ex;}
       .definition .xforms-value {
           height: 5em;
           width: 600px;
       }
           
       /* align the labels but not the save label */
       xf|output xf|label, xf|input xf|label, xf|textarea xf|label, xf|select1 xf|label {
           display: inline-block;
           width: 14ex;
           text-align: right;
           vertical-align: top;
           margin-right: 1ex;
           font-weight: bold;
       }

       xf|input, xf|select1, xf|textarea, xf|ouptut {
           display: block;
           margin: 1ex;
       }
       ]]&gt;
       &lt;/style&gt;
       &lt;xf:model&gt;
           &lt;xf:instance xmlns="" src="{$file}" id="save-data"/&gt;
           &lt;xf:submission id="save" method="post" action="{if ($new='true') then ('save-new.xq') else ('update.xq')}" instance="my-task" replace="all"/&gt;
       &lt;/xf:model&gt;
    &lt;/head&gt;
    &lt;body&gt;
                &lt;h1&gt;Edit Term&lt;/h1&gt;
                
                {if ($id) then
                    &lt;xf:output ref="id" class="id"&gt;
                        &lt;xf:label&gt;ID:&lt;/xf:label&gt;
                    &lt;/xf:output&gt;
                else ()}
                
                &lt;xf:input ref="term-name" class="term-name"&gt;
                    &lt;xf:label&gt;Term Name:&lt;/xf:label&gt;
                &lt;/xf:input&gt;     
                
                &lt;xf:textarea ref="definition" class="definition"&gt;
                    &lt;xf:label&gt;Definition:&lt;/xf:label&gt;
                &lt;/xf:textarea&gt;
                
                &lt;xf:select1 ref="publish-status-code"&gt;
                    &lt;xf:label&gt;Status:&lt;/xf:label&gt;
                    &lt;xf:item&gt;
                        &lt;xf:label&gt;Draft&lt;/xf:label&gt;
                        &lt;xf:value&gt;draft&lt;/xf:value&gt;
                    &lt;/xf:item&gt;
                    &lt;xf:item&gt;
                        &lt;xf:label&gt;Under Review&lt;/xf:label&gt;
                        &lt;xf:value&gt;review&lt;/xf:value&gt;
                    &lt;/xf:item&gt;
                    &lt;xf:item&gt;
                        &lt;xf:label&gt;Published&lt;/xf:label&gt;
                        &lt;xf:value&gt;published&lt;/xf:value&gt;
                    &lt;/xf:item&gt;
                &lt;/xf:select1&gt;
                
                &lt;xf:submit submission="save"&gt;
                    &lt;xf:label&gt;Save&lt;/xf:label&gt;
                &lt;/xf:submit&gt;
    &lt;/body&gt;
&lt;/html&gt;
            
let $xslt-pi := processing-instruction xml-stylesheet {'type="text/xsl" href="/exist/rest/db/xforms/xsltforms/xsltforms.xsl"'}
            
return ($xslt-pi, $form)</programlisting></para><para>Note that this form does "double duty" as both a form for new items and
                    a form for updating existing items. The <emphasis role="bold">new=true</emphasis> parameter must always be passed to the form when
                    creating a new item. Production systems check for these parameters and return
                    error codes if one or the other is not passed to the form.</para><para>All XForms hold the form data in the <emphasis role="bold">&lt;xf:model&gt;</emphasis> element. This form uses a single <emphasis role="bold">&lt;xf:instance&gt;</emphasis> within the model to store the
                    data that will saved when the user clicks the "Save" button. The Save button
                    in XForms is called the <emphasis role="bold">&lt;xf:submit&gt;</emphasis>
                    element. It has a single attribute called the submission attribute that is
                    associated with an <emphasis role="bold">&lt;xf:submission&gt;</emphasis>
                    element within the model. In our example above the name of the submission
                    element (its id) is <emphasis role="bold">save</emphasis>. The save submission
                    element is responsible for sending the data from the XForms client to a specific
                    service on the server. In the example above there are two slightly different
                    XQuery services, one for saving new items and one for updating existing items.
                    We will be covering the save-new and the update queries later in this
                    tutorial.</para><para>The query that is used is wrapped inside of the action attribute of the save
                    submission. Here is the code for this: </para><para><programlisting>action="{if ($new='true') then 
    'save-new.xq'
else 
    'update.xq'
}"</programlisting></para><para>You can see that if the user is creating a new item the data is sent via an
                    HTTP POST to the save-new.xq script. If the user does not have a new item the
                    POST data is sent to the update.xq script.</para><para>Although we could have used a single save.xq script, this structure allows you
                    to trigger different behavior for different functions you may want. For example,
                    the save-new.xq might also trigger an e-mail notification when new records are
                    saved for the first time, or a versioning routine might be triggeed only when
                    the file is updated. Advanced user guides will have examples of both of these
                    functions. <!--reference to future articles.--></para><para>The next section of code to notice is that the ID element is only displayed
                    using a read-only <emphasis role="bold">&lt;xf:output&gt;</emphasis> element if
                    the form is in update mode.</para><para><programlisting>if ($id) then
    &lt;xf:output ref="id" class="id"&gt;
        &lt;xf:label&gt;ID:&lt;/xf:label&gt;
    &lt;/xf:output&gt;
else ()</programlisting></para><para>This shows some of the power of combining XQuery and XForms. In this case we
                    are using logic on the server to conditionally include portions of the form
                    based on the context. The process of using context such as mode, user, group,
                    role, and project is central to understanding how forms can be dynamically
                    created to precisely meet the needs of your users. No more "one size fits all."
                    No more forcing users to fill out fields on forms that are not relevant to their
                    situation. XRX forms can all be dynamically created as they are needed.
                    We can use both client and server logic to determine what features of the form
                    are enabled. XForms includes a function called <emphasis role="bold">&lt;xf:bind&gt;</emphasis> that uses XPath expressions to determine if
                    fields should be displayed. This will also be covered in advanced
                    tutorials. <!--future article.--></para><para>The next item to note is that there are four different user interface controls
                    in this form. The first one is a read-only output. The second is the <emphasis role="bold">&lt;xf:input&gt;</emphasis> control that gathers input in a
                    single line. The third is a <emphasis role="bold">&lt;xf:textarea&gt;</emphasis>
                    control that allows users to enter multi-line descriptions for definitions of
                    terms. The last control is the <emphasis role="bold">&lt;xf:select1&gt;</emphasis> control that allows the user to select one
                    value from a list of values. (For a complete discussion of the XForms controls
                    we suggest you use the XForms Wikibook at <link xlink:href="http://en.wikibooks.org/wiki/XForms">http://en.wikibooks.org/wiki/XForms</link>. The Input Form Controls section
                    goes through each of the controls in the XForms specification. In addition to
                    the standard controls there are other controls that can also be integrated
                    directly into XForms, such as rich-text editors.)</para><para>Each of the input controls has a <emphasis role="bold">ref</emphasis>
                    attribute that indicates which element in the instance it is bound to. If you
                    have multiple instances and multiple models you may not be able to use all the
                    default values as in this example. This ref attribute is how leaf elements the
                    model get bound to each input control. In general, when you are building simple,
                    flat forms there is a one-to-one correspondence between the form elements and
                    the instances in the model. Complex forms also allow you to have repeating
                    elements so you can add one-to-many structures in a form. This means that XForms
                    are not restricted to managing a flat list of elements. They can contain
                    multiple nested elements with elements. This will also be discussed in advanced
                    tutorials. <!--future article.--></para><para>The final part of the form contains the instructions needed to place the
                    XSLTForms processing instruction at the top of the file when it is
                    rendered.</para><para><programlisting>let $xslt-pi := processing-instruction xml-stylesheet 
    {'type="text/xsl" href="/exist/rest/db/xforms/xsltforms/xsltforms.xsl"'}
return ($xslt-pi, $form)</programlisting></para><para>You can also add a directive that will put the XSLTForms system into a debug
                    mode by adding the following .</para><para><programlisting>let $debug := processing-instruction xsltforms-options {'debug="yes"'}
return ($xslt-pi, $debug, $form)</programlisting></para></section><section><title>Saving New Items</title><para>The save new item process must first access the XML file that stores the next ID to
                    be used to create a unique file name. We store the next ID to be used in a small
                    XML file with only one element in the root called <emphasis role="bold">next-id</emphasis>. Here is that file: </para><para><emphasis role="bold">/db/apps/terms/edit/next-id.xml</emphasis></para><para><programlisting>&lt;data&gt;
    &lt;next-id&gt;6&lt;/next-id&gt;
&lt;/data&gt;</programlisting></para><para>The <emphasis role="bold">&lt;next-id&gt;</emphasis> element is updated using
                    an XQuery "update function" when new items are saved to the data collection. We
                    save the file using the number as the filename; in this case, the next file
                    saved will be 6.xml. After the file is saved, the "next id" number is
                    incremented to 7. (This is similar to the auto-increment function in many other
                    databases. eXist also has a counter function that you can use.<!--reference needed-->) Using an
                    arbitrary number as an ID is sometimes called a "surrogate key" <!--was: foreign key-->since it is
                    external to the actual data in the XML file.</para><para>When you create files, sometimes you want to create an identifier that is not
                    just a number but it might also serve some meaning to allow users to
                    differentiate items in a collection. For example a database of countries might
                    use a country name as the file name. You can also allow users to pick an
                    identifier and check for duplicates as they enter the data. This will be covered
                    in advanced sections. <!--future article--></para><para><emphasis role="bold">/db/apps/terms/edit/save-new.xq</emphasis></para><para><programlisting>xquery version "1.0";

declare option exist:serialize "method=xhtml media-type=text/html indent=yes";
 
let $app-collection := '/db/apps/terms'
let $data-collection := '/db/apps/terms/data'
 
(: get the form data that has been "POSTed" to this XQuery :)
let $item := request:get-data()
 
(: get the next ID from the next-id.xml file :)
let $next-id-file-path := concat($app-collection,'/edit/next-id.xml')
let $id := doc($next-id-file-path)/data/next-id/text() 
let $file := concat($id, '.xml')

(: logs into the collection :)
let $login := xmldb:login($app-collection, 'admin', 'myadminpassword')

(: create the new file with a still-empty id element :)
let $store := xmldb:store($data-collection, $file, $item)

(: add the correct ID to the new document we just saved :)
let $update-id :=  update replace doc(concat($data-collection, '/', $file))/term/id with &lt;id&gt;{$id}&lt;/id&gt;

(: update the next-id.xml file :)
let $new-next-id :=  update replace doc($next-id-file-path)/data/next-id/text() with ($id + 1)

(: we need to return the original ID number in our results, but $id has already been increased by 1 :)
let $original-id := ($id - 1)

return
&lt;html&gt;
    &lt;head&gt;
       &lt;title&gt;Save Conformation&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;a href="../index.xhtml"&gt;Term Home&lt;/a&gt;
        &lt;p&gt;Term {$original-id} has been saved.&lt;/p&gt;
        &lt;a href="../views/list-items.xq"&gt;List all Terms&lt;/a&gt; 
    &lt;/body&gt;
&lt;/html&gt;</programlisting></para></section><section><title>Updating Existing Items</title><para>The update function is simpler than the save function, since it does not have
                    to worry about creating a new file and incrementing a counter. It simply takes
                    the incoming POST data and stores it in the file. Note that by default this
                    means that the entire data file is updated and reindexed upon the store
                    operation. (Note that eXist contains a versioning system which can be enabled by simply
                    configuring a single XML file in the /db/system/config area.) <!--expand--></para><para><emphasis role="bold"> /db/apps/terms/edit/update.xq </emphasis></para><para><programlisting>xquery version "1.0";

declare option exist:serialize "method=xhtml media-type=text/html indent=yes";
 
let $title := 'Update Confirmation'
let $data-collection := '/db/apps/terms/data'
 
(: get the form data that has been "POSTed" to this XQuery :)
let $item := request:get-data()
 
(: log into the collection :)
let $login := xmldb:login($data-collection, 'admin', 'myadminpassword')

(: get the id out of the posted document :)
let $id := $item/term/id/text() 

let $file := concat($id, '.xml') 
 
(: save the new file, overwriting the old one :)
let $store := xmldb:store($data-collection, $file, $item)

return
&lt;html&gt;
    &lt;head&gt;
       &lt;title&gt;{$title}&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
    &lt;h1&gt;{$title}&lt;/h1&gt;
    &lt;p&gt;Item {$id} has been updated.&lt;/p&gt;
    &lt;/body&gt;
&lt;/html&gt;</programlisting></para></section></section><section><title>Deleting</title><para>Deleting items is even simpler than editing items. There are only two files that
                we will need to create. Each of them takes a single REST parameter. The first file is
                a confirmation XQuery script that just asks the user "Are you sure you want to
                delete this term?" The second script actually performs the deletion.</para><section><title>Confirming Delete</title><para>The delete confirmation script takes the ID of the item to be deleted and
                    opens the document using the doc() function. It then presents the user with
                    details about the item and displays two choices. One to delete and the other to
                    cancel the delete. A CSS file can be used to color the links appropriately with
                    a red warning indicator.</para><para><emphasis role="bold">/db/apps/terms/edit/delete-confirm.xq</emphasis></para><para><programlisting>xquery version "1.0";

declare option exist:serialize "method=xhtml media-type=text/html indent=yes";

let $id := request:get-parameter("id", "")

let $data-collection := '/db/apps/terms/data/'
let $doc := concat($data-collection, $id, '.xml')

return
&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;Delete Confirmation&lt;/title&gt;
        &lt;style&gt;
        &lt;![CDATA[
        .warn {background-color: silver; color: black; font-size: 16pt; line-height: 24pt; padding: 5pt; border: solid 2px black;}
        ]]&gt;
        &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;a href="../index.xhtml"&gt;Item Home&lt;/a&gt; &amp;gt; &lt;a href="../views/list-items.xq"&gt;List Items&lt;/a&gt;
        &lt;h1&gt;Are you sure you want to delete this term?&lt;/h1&gt;
        &lt;strong&gt;Name: &lt;/strong&gt;{doc($doc)/term/term-name/text()}&lt;br/&gt;
        &lt;strong&gt;Path: &lt;/strong&gt; {$doc}&lt;br/&gt;
        &lt;br/&gt;
        &lt;a class="warn" href="delete.xq?id={$id}"&gt;Yes - Delete This Term&lt;/a&gt;
        &lt;br/&gt;
        &lt;br/&gt;
        &lt;a  class="warn" href="../views/view-item.xq?id={$id}"&gt;Cancel (Back to View Term)&lt;/a&gt;
    &lt;/body&gt;
&lt;/html&gt;</programlisting></para></section></section><section><title>The Delete Script</title><para>The delete script also takes a single REST parameter of the ID</para><para><emphasis role="bold">/db/apps/terms/edit/delete.xq </emphasis></para><para><programlisting>xquery version "1.0";

declare option exist:serialize "method=xhtml media-type=text/html indent=yes";
 
let $data-collection := '/db/apps/terms/data'
 
(: get the id parameter from the URL :)
let $id := request:get-parameter('id', '')

(: log into the collection :)
let $login := xmldb:login($data-collection, 'admin', 'myadminpassword')

(: construct the filename from the id :)
let $file := concat($id, '.xml')

(: delete the file :)
let $store := xmldb:remove($data-collection, $file)

return
&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;Delete Term&lt;/title&gt;
        &lt;style&gt;
            &lt;![CDATA[
               .warn  {background-color: silver; color: black; font-size: 16pt; line-height: 24pt; padding: 5pt; border:solid 2px black;}
            ]]&gt;
        &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;a href="../index.xhtml"&gt;Terms Home&lt;/a&gt; &amp;gt; &lt;a href="../views/list-items.xq"&gt;List Terms&lt;/a&gt;&lt;br/&gt;
        &lt;h1&gt;Term id {$id} has been removed.&lt;/h1&gt;
    &lt;/body&gt;
&lt;/html&gt;</programlisting></para></section><section><title>The Application Home Page</title><para>A simple application home page can be a description of the application and a
                static list of links to the main entry points of the application: the item lister,
                the search form, the create new and the reindex. The index page can be a static HTML
                page as describe below.</para><para><emphasis role="bold">/db/apps/terms/index.html</emphasis></para><para><programlisting>&lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;Terms&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;h1&gt;Terms&lt;/h1&gt;
        &lt;a href="views/list-items.xq"&gt;List Items&lt;/a&gt;
        &lt;br/&gt;
        &lt;a href="search/search-form.html"&gt;Search&lt;/a&gt;
        &lt;br/&gt;
        &lt;a href="edit/edit.xq?new=true"&gt;Create New Term&lt;/a&gt;
        &lt;br/&gt;
        &lt;a href="admin/reindex.xq"&gt;Reindex the collection&lt;/a&gt;
        &lt;br/&gt;
    &lt;/body&gt;
&lt;/html&gt;</programlisting></para><para><inlinemediaobject><imageobject><imagedata fileref="resources/index.png" contentwidth="200"/></imageobject></inlinemediaobject></para></section><section><title>Next Steps</title><para>As you have now learned all of the CRUDS functions, you are now ready to move
                on the some more complex examples. Here are some suggestions for the next steps you can take. <orderedlist><listitem><para>Create a collection /db/apps/modules and add a file called style.xml
                            in that collection. Add XQuery functions for style:header(),
                            style:footer() and then reference these functions in each of your HTML
                            web pages.</para></listitem><listitem><para>Change the list-items.xq to use HTML tables to view each item.</para></listitem><listitem><para>Use the eXist-db permission system to create a groups called "editor"
                            and a group called "term-admin". Change the group permissions on the
                            edit and admin collections to only allow users in these groups to be
                            able to access these collections.</para></listitem><listitem><para>In the list-items.xq query, use XQuery sequences to pre-sort items and
                            then display only an initial subset of the data using the subsequence
                            function.</para></listitem><listitem><para>Add URL parameters <emphasis role="bold">start</emphasis> and
                                <emphasis role="bold">num</emphasis> to the list-items to indicate
                            what record to start to display and how many records to display.</para></listitem><listitem><para>Learn how to create one-to-many relationships in your forms using the
                                <emphasis role="bold">&lt;xf:repeat&gt;</emphasis> element. For
                            example, create a form that allows you to add multiple phone numbers to a
                            contact record or multiple authors to a book entry.</para></listitem><listitem><para>Learn how to use XForms binding to conditionally display elements in a
                            form.</para></listitem><listitem><para>Get fancy with how tables of data are displayed. Add sorting to table
                            columns.</para></listitem><listitem><para>Add security to your forms by only allowing people in an "edit" group
                            to be able to write to the data collection.</para><para>Create roles for users such as editor, publisher and then copy the XML
                            files to a remote host using the http-client() functions.</para></listitem><listitem><para>Add forms that edit complex data using in-browser lists and
                            inspectors.</para></listitem><listitem><para>Create forms that manage document workflows. Add workflow steps that
                            flow to the right as they expand.</para></listitem><listitem><para>Create advanced search forms that use multiple selection criteria such
                            as document types, authors or date ranges.</para></listitem><listitem><para>Create complex business logic in how selection lists can be
                            controlled. Use one selection list to control the values of a second
                            selection list.</para></listitem><listitem><para>Move all of the codes in the publish-status selection list into an XML
                            file and place it in a collection called <emphasis role="bold">code-tables</emphasis>. Then add an instance to the form that reads
                            this code table into the form.</para></listitem><listitem><para>Add a XQuery function that will take a status codes value and return
                            its label.</para></listitem><listitem><para>Modify the system configuration file for the /db/apps/terms/data
                            collection to enable versioning when items are updated.</para></listitem></orderedlist></para></section><section><title>References</title><para>All of these topics and many more are covered in the XQuery, XForms and XRX
                Wikibooks. You can use the search tools within each Wikibook to find how specific
                elements are used within each of the examples.</para><bibliography><title>Bibliography</title><bibliodiv><title>Wiki Books</title><biblioentry xreflabel="xforms-wiki"><title>XForms Wikibook</title><bibliosource>http://en.wikibooks.org/wiki/XForms</bibliosource><author><personname><firstname>Dan</firstname><surname>McCreary</surname></personname></author></biblioentry><biblioentry xreflabel="xrx-wiki"><title>XRX Wikibook</title><bibliosource>http://en.wikibooks.org/wiki/XRX</bibliosource><author><personname><firstname>Dan</firstname><surname>McCreary</surname></personname></author></biblioentry><biblioentry xreflabel="xquery-wiki"><title>XQuery Wikibook</title><bibliosource>http://en.wikibooks.org/wiki/XQuery</bibliosource><author><personname><firstname>Chris</firstname><surname>Wallace</surname></personname></author><author><personname><firstname>Dan</firstname><surname>McCreary</surname></personname></author></biblioentry>
                    <!--deleted dubinko included below--></bibliodiv><bibliodiv><title>Articles</title><biblioentry xreflabel="wikipedia-xrx"><title>XRX (web application architecture)</title><bibliosource>http://en.wikipedia.org/wiki/XRX_%28web_application_architecture%29</bibliosource></biblioentry><biblioentry xreflabel="tennison-xrx-in-exist"><title>XRX: XQueries in eXist</title><author><personname><firstname>Jeni</firstname><surname>Tennison</surname></personname></author><bibliosource>http://news.oreilly.com/2008/07/xrx-xqueries-in-exist.html</bibliosource></biblioentry><biblioentry xreflabel="simple_elegant_disruptive"><title>XRX: Simple, Elegant, Disruptive</title><author><personname><firstname>Dan</firstname><surname>McCreary</surname></personname></author><bibliosource>http://www.oreillynet.com/xml/blog/2008/05/xrx_a_simple_elegant_disruptiv_1.html</bibliosource></biblioentry></bibliodiv><bibliodiv><title>Books</title><biblioentry xreflabel="walmsley"><title>XQuery</title><author><personname><firstname>Priscilla</firstname><surname>Walmsley</surname></personname></author><publisher><publishername>O'Reilly Publishing</publishername></publisher><copyright><year>2007</year></copyright></biblioentry><biblioentry xreflabel="dubinko"><title>XForms Essentials</title><author><personname><firstname>Micah</firstname><surname>Dubinko</surname></personname></author><publisher><publishername>O'Reilly Publishing</publishername></publisher><copyright><year>2003</year></copyright></biblioentry></bibliodiv></bibliography></section></chapter></book>