W3C

XQuery Update Facility Use Cases

W3C Working Draft 27 January 2006

This version:
http://www.w3.org/TR/2006/WD-xqupdateusecases-20060127/
Latest version:
http://www.w3.org/TR/xqupdateusecases/
Editors:
Ioana Manolescu, INRIA <ioana.manolescu@inria.fr>
Jonathan Robie, DataDirect Technologies <jonathan.robie@datadirect.com>

Abstract

This document specifies usage scenarios for the XQuery Update Facility.

Status of this Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This document has been produced by the XML Query Working Group (part of the XML Activity), following the procedures set out in the W3C Process Document. This is the first version of this document.

This is the First Public Working Draft for review by W3C members and other interested parties. Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This document corresponds to the current XQuery Update Facility Working Draft. The queries in this document have been parsed using a parser generated from the same grammar used to create the documentation for the XQuery Update Facility. The use cases currently contained in this document may be changed in future versions - several use cases are already under development (including some suggested by the public), and the Working Group expects to continue adding use cases. The Working Group also reserves the right to decide not to support use cases currently shown in this document.

Public comments on this document and its open issues are invited. Comments on this document should be made in W3C's public Bugzilla system (instructions can be found at http://www.w3.org/XML/2005/04/qt-bugzilla). When entering comments, select the Product named "XPath / XQuery / XSLT", the Component named "Update Facility Use Cases", and the Version named "Working drafts". If access to that system is not feasible, you may send your comments to the W3C XSLT/XPath/XQuery mailing list, public-qt-comments@w3.org. It will be very helpful if you include the string [UPDUseCases] in the subject line of your comment, whether made in Bugzilla or in email. Each Bugzilla entry and email message should contain only one comment. Archives of the comments and responses are available at http://lists.w3.org/Archives/Public/public-qt-comments/.

As of this publication, the Working Group expects to eventually publish this document as a Working Group Note. It is not expected to become a W3C Recommendation, and therefore it has no associated W3C Patent Policy licensing obligations.

Per section 4 of the W3C Patent Policy, Working Group participants have 150 days from the title page date of this document to exclude essential claims from the W3C RF licensing requirements with respect to this document series. Exclusions are with respect to the exclusion reference document, defined by the W3C Patent Policy to be the latest version of a document in this series that is published no later than 90 days after the title page date of this document.

Table of Contents

1 Use Cases for XQuery Updates
    1.1 Use Case "R" - Updating Relational Data
        1.1.1 Description
        1.1.2 Document Type Definition (DTD)
            1.1.2.1 DTD for users.xml
            1.1.2.2 DTD for items.xml
            1.1.2.3 DTD for bids.xml
        1.1.3 Input Data
        1.1.4 Updates and Results
            1.1.4.1 Q1
            1.1.4.2 Q2
            1.1.4.3 Q3
            1.1.4.4 Q4
            1.1.4.5 Q5
            1.1.4.6 Q6
            1.1.4.7 Q7
            1.1.4.8 Q8
            1.1.4.9 Q9
            1.1.4.10 Q10
    1.2 Use Case "Address Book" - Synchronizing address book entries
        1.2.1 Input Data
        1.2.2 Q1
    1.3 Use Case "SOAP"
        1.3.1 Input Data
        1.3.2 Q1

Appendix

A Normative References


1 Use Cases for XQuery Updates

The use cases listed below were created by the XML Query Working Group to illustrate important applications for an XML update facility. Each use case is focused on a specific application area, and contains a Document Type Definition (DTD) and example input data. Each use case specifies a set of updates that might be applied to the input data, and the expected resulting value of the modified input for each update. Since the English description of each query is concise, the expected results form an important part of the definition of each update directive, specifying the expected result. These use cases are inspired by the W3C XQuery Update Facility Requirements document.

These use cases represent a snapshot of an ongoing work. Some important application areas and important operations are not yet adequately covered by a use case. The XML Query Working Group reserves the right to add, delete, or modify individual queries or whole use cases as the work progresses. The presence of a query in this set of use cases does not necessarily indicate that the query will be expressible in the XQuery Update Facility to be created by the XML Query Working Group.

1.1 Use Case "R" - Updating Relational Data

One important use of an XML update language will be to update data stored in relational databases. This use case describes a set of such possible updates.

1.1.1 Description

This use case is based on performing updates on the data used in Use Case "R" from the [XML Query Use Cases]. The DTD and sample data from this Use Case are copied below for convenience, and exactly match those found in the XQuery Use Cases.

The data represents a relational database used by an online auction. The auction maintains a USERS table containing information on registered users, each identified by a unique userid, who can either offer items for sale or bid on items. An ITEMS table lists items currently or recently for sale, with the userid of the user who offered each item. A BIDS table contains all bids on record, keyed by the userid of the bidder and the item number of the item to which the bid applies.

The three tables used by the online auction are below, with their column-names indicated in parentheses.

USERS ( USERID, NAME, RATING ) 
ITEMS ( ITEMNO, DESCRIPTION, OFFERED_BY, START_DATE, END_DATE, RESERVE_PRICE ) 
BIDS ( USERID, ITEMNO, BID, BID_DATE )

1.1.2 Document Type Definition (DTD)

This use case is based on three separate input documents named users.xml, items.xml, and bids.xml. Each of the documents represents one of the tables in the relational database described above, using the following DTDs:

1.1.2.1 DTD for users.xml
                                            
<!ELEMENT users (user_tuple*)> 
<!ELEMENT user_tuple (userid, name, rating?)> 
<!ELEMENT userid (#PCDATA)> 
<!ELEMENT name (#PCDATA)> 
<!ELEMENT rating (#PCDATA)>
 
1.1.2.2 DTD for items.xml
                  
<!ELEMENT items (item_tuple*)>
<!ELEMENT item_tuple (itemno, description, offered_by, start_date?, end_date?, reserve_price?)> 
<!ELEMENT itemno (#PCDATA)>
<!ELEMENT description (#PCDATA)>
<!ELEMENT offered_by (#PCDATA)>
<!ELEMENT start_date (#PCDATA)>
<!ELEMENT end_date (#PCDATA)>
<!ELEMENT reserve_price (#PCDATA)>
                
1.1.2.3 DTD for bids.xml
                      
<!ELEMENT bids (bid_tuple*)> 
<!ELEMENT bid_tuple (userid, itemno, bid, bid_date)> 
<!ELEMENT userid (#PCDATA)> 
<!ELEMENT itemno (#PCDATA)> 
<!ELEMENT bid (#PCDATA)>
<!ELEMENT bid_date (#PCDATA)>
                      

1.1.3 Input Data

Here is an abbreviated set of data showing the XML format of the instances:

<items>
  <item_tuple>
    <itemno>1001</itemno>
    <description>Red Bicycle</description>
    <offered_by>U01</offered_by>
    <start_date>1999-01-05</start_date>
    <end_date>1999-01-20</end_date>
    <reserve_price>40</reserve_price>
  </item_tuple>
  <!-- !!! Snip !!! -->

<users>
  <user_tuple>
    <userid>U01</userid>
    <name>Tom Jones</name>
    <rating>B</rating>
  </user_tuple>
  <!-- !!! Snip !!! -->

<bids>
  <bid_tuple> 
    <userid>U02</userid> 
    <itemno>1001</itemno> 
    <bid>35</bid> 
    <bid_date>1999-01-07</bid_date> 
    </bid_tuple> 
  <bid_tuple> 
  <!-- !!! Snip !!! -->
                    

The entire data set is represented by the following table:

USERS
USERID NAME RATING
U01 Tom Jones B
U02 Mary Doe A
U03 Dee Linquent D
U04 Roger Smith C
U05 Jack Sprat B
U06 Rip Van Winkle B
ITEMS
ITEMNO DESCRIPTION OFFERED_BY START_DATE END_DATE RESERVE_PRICE
1001 Red Bicycle U01 1999-01-05 1999-01-20 40
1002 Motorcycle U02 1999-02-11 1999-03-15 500
1003 Old Bicycle U02 1999-01-10 1999-02-20 25
1004 Tricycle U01 1999-02-25 1999-03-08 15
1005 Tennis Racket U03 1999-03-19 1999-04-30 20
1006 Helicopter U03 1999-05-05 1999-05-25 50000
1007 Racing Bicycle U04 1999-01-20 1999-02-20 200
1008 Broken Bicycle U01 1999-02-05 1999-03-06 25
BIDS
USERID ITEMNO BID BID_DATE
U02 1001 35 1999-01-07
U04 1001 40 1999-01-08
U02 1001 45 1999-01-11
U04 1001 50 1999-01-13
U02 1001 55 1999-01-15
U01 1002 400 1999-02-14
U02 1002 600 1999-02-16
U03 1002 800 1999-02-17
U04 1002 1000 1999-02-25
U02 1002 1200 1999-03-02
U04 1003 15 1999-01-22
U05 1003 20 1999-02-03
U01 1004 40 1999-03-05
U03 1007 175 1999-01-25
U05 1007 200 1999-02-08
U04 1007 225 1999-02-12

1.1.4 Updates and Results

1.1.4.1 Q1

Add a new user (with no rating) to the users.xml view.

Solution in XQuery:

insert {
  <user_tuple>
    <userid>U07</userid>
    <name>Annabel Lee</name>
  </user_tuple>
 }
into doc("users.xml")/users

Expected resulting content of users.xml:

<users>
  <user_tuple>
    <userid>U01</userid>
    <name>Tom Jones</name>
    <rating>B</rating>
  </user_tuple>
  <user_tuple>
    <userid>U02</userid>
    <name>Mary Doe</name>
    <rating>A</rating>
  </user_tuple>
  <!-- !!! Snip !!! -->
  <user_tuple>
   <userid>U06</userid>
   <name>Rip Van Winkle</name>
   <rating>B</rating>
  </user_tuple>
  <user_tuple>
    <userid>U07</userid>
    <name>Annabel Lee</name>
  </user_tuple>
</users>
                                                
1.1.4.2 Q2

Enter a bid for user Annabel Lee on February 1st, 1999 for 60 dollars on item 1001.

Solution in XQuery:

let $uid := doc("users.xml")/users/user_tuple[name="Annabel Lee"]/userid
do
  insert {
    <bid_tuple> 
      <userid>{data($uid)}</userid> 
      <itemno>1001</itemno> 
      <bid>60</bid> 
      <bid_date>1999-02-01</bid_date> 
    </bid_tuple>
   }
  into doc("bids.xml")/bids 

Expected resulting content of bids.xml:

<bids>
  <bid_tuple> 
    <userid>U02</userid> 
    <itemno>1001</itemno> 
    <bid>35</bid> 
    <bid_date>1999-01-07</bid_date> 
  </bid_tuple> 
   <bid_tuple> 
    <userid>U04</userid> 
    <itemno>1001</itemno> 
    <bid>40</bid> 
    <bid_date>1999-01-08</bid_date> 
  </bid_tuple> 
  <!-- !!! Snip !!! -->
  <bid_tuple> 
    <userid>U01</userid> 
    <itemno>1002</itemno> 
    <bid>400</bid> 
    <bid_date>1999-02-14</bid_date> 
  </bid_tuple> 
  <!-- !!! Snip !!! -->
   <bid_tuple> 
    <userid>U04</userid> 
    <itemno>1007</itemno> 
    <bid>225</bid> 
    <bid_date>1999-02-12</bid_date> 
  </bid_tuple> 
  <bid_tuple> 
    <userid>U07</userid> 
    <itemno>1001</itemno> 
    <bid>60</bid> 
    <bid_date>1999-02-01</bid_date> 
  </bid_tuple> 
</bids>
                                                
1.1.4.3 Q3

Modify the value of Annabel Lee's bid on item 1001, from 60 to 65 dollars.

Solution in XQuery:

let $user := doc("users.xml")/users/user_tuple[name="Annabel Lee" and bid="60" and bid_date="1999-02-01"]
do replace value of {$user/bid} with 65

Expected resulting content of bids.xml:

<bids>
  <bid_tuple> 
    <userid>U02</userid> 
    <itemno>1001</itemno> 
    <bid>35</bid> 
    <bid_date>1999-01-07</bid_date> 
  </bid_tuple> 
   <bid_tuple> 
    <userid>U04</userid> 
    <itemno>1001</itemno> 
    <bid>40</bid> 
    <bid_date>1999-01-08</bid_date> 
  </bid_tuple> 
  <!-- !!! Snip !!! -->
  <bid_tuple> 
    <userid>U07</userid> 
    <itemno>1001</itemno> 
    <bid>65</bid> 
    <bid_date>1999-02-01</bid_date> 
  </bid_tuple> 
  <bid_tuple> 
    <userid>U01</userid> 
    <itemno>1002</itemno> 
    <bid>400</bid> 
    <bid_date>1999-02-14</bid_date> 
  </bid_tuple> 
  <!-- !!! Snip !!! -->
   <bid_tuple> 
    <userid>U04</userid> 
    <itemno>1007</itemno> 
    <bid>225</bid> 
    <bid_date>1999-02-12</bid_date> 
  </bid_tuple> 
</bids>
                                                
1.1.4.4 Q4

Insert a new bid for Annabel Lee on item 1002, adding 10% to the best bid received so far for this item.

Solution in XQuery:

let $uid := doc("users.xml")/users/user_tuple[name="Annabel Lee"]/userid
let $topbid := max(doc("bids.xml")/bids/bid_tuple[itemno=1002]/bid)
do
  insert {
    <bid_tuple> 
      <userid>{data($uid)}</userid> 
      <itemno>1002</itemno> 
      <bid>{$topbid*1.1}</bid> 
      <bid_date>1999-02-01</bid_date> 
    </bid_tuple>
   }
  into doc("bids.xml")/bids

Expected resulting content of bids.xml:

<bids>
  <bid_tuple> 
    <userid>U02</userid> 
    <itemno>1001</itemno> 
    <bid>35</bid> 
    <bid_date>1999-01-07</bid_date> 
  </bid_tuple> 
  <!-- !!! Snip !!! -->
  <bid_tuple> 
    <userid>U01</userid> 
    <itemno>1002</itemno> 
    <bid>400</bid> 
    <bid_date>1999-02-14</bid_date> 
  </bid_tuple> 
  <!-- !!! Snip !!! -->
   <bid_tuple> 
    <userid>U04</userid> 
    <itemno>1007</itemno> 
    <bid>225</bid> 
    <bid_date>1999-02-12</bid_date> 
  </bid_tuple> 
  <!-- !!! Snip !!! -->
  <bid_tuple> 
    <userid>U07</userid> 
    <itemno>1002</itemno> 
    <bid>1320</bid> 
    <bid_date>1999-03-05</bid_date> 
  </bid_tuple> 
</bids>
                                                

The best bid for item 1002 had been at 1200, thus Annabel's bid is at 1320.

1.1.4.5 Q5

Set Annabel Lee's rating to B.

Solution in XQuery:

let $user := doc("users.xml")/users/user_tuple[name="Annabel Lee"]
do replace value of {$user/rating} with "B"

Expected resulting content of users.xml:

<users>
  <user_tuple>
    <userid>U01</userid>
    <name>Tom Jones</name>
    <rating>B</rating>
  </user_tuple>
  <user_tuple>
    <userid>U02</userid>
    <name>Mary Doe</name>
    <rating>A</rating>
  </user_tuple>
  <!-- !!! Snip !!! -->
  <user_tuple>
   <userid>U06</userid>
   <name>Rip Van Winkle</name>
   <rating>B</rating>
  </user_tuple>
  <user_tuple>
    <userid>U07</userid>
    <name>Annabel Lee</name>
    <rating>B</rating>
  </user_tuple>
</users>
                                                
1.1.4.6 Q6

Place a a bid for Annabel Lee on item 1007, adding 10% to the best bid received so far on that item, but only if the bid amount does not exceed a given limit. The first query illustrates the desired behavior if the limit is exceeded.

Solution in XQuery:

let $uid := doc("users.xml")/users/user_tuple[name="Annabel Lee"]/userid
let $topbid := max(doc("bids.xml")/bids/bid_tuple[itemno=1007]/bid)
where $topbid*1.1 <= 200
do
  insert {
    <bid_tuple> 
      <userid>{data($uid)}</userid> 
      <itemno>1007</itemno> 
      <bid>{$topbid*1.1}</bid> 
      <bid_date>1999-02-01</bid_date> 
    </bid_tuple>
   }
  into doc("bids.xml")/bids

Expected resulting content of bids.xml:

<bids>
  <bid_tuple> 
    <userid>U02</userid> 
    <itemno>1001</itemno> 
    <bid>35</bid> 
    <bid_date>1999-01-07</bid_date> 
  </bid_tuple> 
  <!-- !!! Snip !!! -->
   <bid_tuple> 
    <userid>U04</userid> 
    <itemno>1007</itemno> 
    <bid>225</bid> 
    <bid_date>1999-02-12</bid_date> 
  </bid_tuple> 
</bids>
                                                

In the above, adding 10% to the best bid on item 1007 would have required a bid of 237, which is more than the allowed limit of 200. Thus, the bids.xml document does not change.

Place a a bid for Annabel Lee on item 1007, adding 10% to the best bid received so far on that item, but only if the bid amount does not exceed 500. This illustrates the behavior when the resulting value is within the limit.

Solution in XQuery:

let $uid := doc("users.xml")/users/user_tuple[name="Annabel Lee"]/userid
let $topbid := max(doc("bids.xml")/bids/bid_tuple[itemno=1007]/bid)
where $topbid*1.1 <= 500
do
  insert {
    <bid_tuple> 
      <userid>{data($uid)}</userid> 
      <itemno>1007</itemno> 
      <bid>{$topbid*1.1}</bid> 
      <bid_date>1999-02-01</bid_date> 
    </bid_tuple>
   }
  into doc("bids.xml")/bids

Expected resulting content of bids.xml

<bids>
  <bid_tuple> 
    <userid>U02</userid> 
    <itemno>1001</itemno> 
    <bid>35</bid> 
    <bid_date>1999-01-07</bid_date> 
  </bid_tuple> 
  <!-- !!! Snip !!! -->
   <bid_tuple> 
    <userid>U04</userid> 
    <itemno>1007</itemno> 
    <bid>225</bid> 
    <bid_date>1999-02-12</bid_date> 
  </bid_tuple> 
  <bid_tuple> 
    <userid>U07</userid> 
    <itemno>1007</itemno> 
    <bid>237</bid> 
    <bid_date>1999-04-01</bid_date> 
  </bid_tuple> 
</bids>
                                                
1.1.4.7 Q7

Erase user Dee Linquent and the corresponding associated items and bids.

Solution in XQuery:

let $user := doc("users.xml")/users/user_tuple[name="Dee Linquent"]
let $items := doc("items.xml")/items/item_tuple[offered_by=$user/userid]
let $bids := doc("bids.xml")/bids/bid_tuple[userid=$user/userid]
do (
  delete {$user},
  delete {$items},
  delete {$bids}
)

Expected resulting content of items.xml:

<items>
  <item_tuple>
    <itemno>1001</itemno>
    <description>Red Bicycle</description>
    <offered_by>U01</offered_by>
    <start_date>1999-01-05</start_date>
    <end_date>1999-01-20</end_date>
    <reserve_price>40</reserve_price>
  </item_tuple>
  <!-- !!! Snip !!! -->
  <item_tuple>
    <itemno>1004</itemno>
    <description>Tricycle</description>
    <offered_by>U01</offered_by>
    <start_date>1999-02-25</start_date>
    <end_date>1999-03-08</end_date>
    <reserve_price>15</reserve_price>
  </item_tuple>
   <item_tuple>
    <itemno>1007</itemno>
    <description>Racing bicycle</description>
    <offered_by>U04</offered_by>
    <start_date>1999-01-20</start_date>
    <end_date>1999-02-20</end_date>
    <reserve_price>200</reserve_price>
  </item_tuple>
   <item_tuple>
    <itemno>1008</itemno>
    <description>Broken bicycle</description>
    <offered_by>U01</offered_by>
    <start_date>1999-02-05</start_date>
    <end_date>1999-03-06</end_date>
    <reserve_price>25</reserve_price>
  </item_tuple>
</items>
                                                

In the above, items 1005 and 1006, offered by user Dee Linquent, have been erased; item 1007 now directly follows item 1004. Notice that the whole subtrees rooted at the corresponding <item_tuple> elements have been erased.

Expected resulting content of users.xml:

<users>
  <user_tuple>
    <userid>U01</userid>
    <name>Tom Jones</name>
    <rating>B</rating>
  </user_tuple>
  <user_tuple>
    <userid>U02</userid>
    <name>Mary Doe</name>
    <rating>A</rating>
  </user_tuple>
   <user_tuple>
    <userid>U04</userid>
    <name>Roger Smith</name>
    <rating>C</rating>
  </user_tuple>
  <!-- !!! Snip !!! -->
  <user_tuple>
   <userid>U06</userid>
   <name>Rip Van Winkle</name>
   <rating>B</rating>
  </user_tuple>
</users>
                                                

In the above, user Dee Linquent has been erased.

Expected resulting content of bids.xml:

<bids>
  <bid_tuple> 
    <userid>U02</userid> 
    <itemno>1001</itemno> 
    <bid>35</bid> 
    <bid_date>1999-01-07</bid_date> 
  </bid_tuple> 
   <bid_tuple> 
    <userid>U04</userid> 
    <itemno>1001</itemno> 
    <bid>40</bid> 
    <bid_date>1999-01-08</bid_date> 
  </bid_tuple> 
  <!-- !!! Snip !!! -->
  <bid_tuple> 
    <userid>U02</userid> 
    <itemno>1002</itemno> 
    <bid>600</bid> 
    <bid_date>1999-02-16</bid_date> 
  </bid_tuple> 
  <bid_tuple> 
    <userid>U04</userid> 
    <itemno>1002</itemno> 
    <bid>1000</bid> 
    <bid_date>1999-02-25</bid_date> 
  </bid_tuple> 
  <!-- !!! Snip !!! -->
  <bid_tuple> 
    <userid>U04</userid> 
    <itemno>1007</itemno> 
    <bid>225</bid> 
    <bid_date>1999-02-12</bid_date> 
  </bid_tuple> 
</bids>

                                                

No bids had been placed on items 1005 and 1006 offered by user Dee Linquent. However, Dee Linquent had placed a bid on item 1002; this bid has been erased.

1.1.4.8 Q8

Add the element <comment>This is a bargain !</comment> as the last child of the <item> element describing item 1002.

Solution in XQuery

insert {
  <comment>This is a bargain !</comment>
}
as last into doc("items.xml")/items/item_tuple[itemno=1002] 
                                                

Expected resulting content of items.xml: The same as the original contents.

The items.xml document is unchanged and an error is raised. This update can not be applied without rendering the document invalid with respect to its schema.

1.1.4.9 Q9

Place a bid for Annabel Lee on item 1010, which does not exist in "bids.xml".

Solution in XQuery: No solution provided.

Expected resulting content of bids.xml: the same as the original contents.

This query was designed to explore referential integrity constraints. Unfortunately, with the current mapping, we can not express these constraints with a W3C XML Schema, since there are three different XML files, and no schema can span them. How do we account for such constraints, which may well be implemented in an underlying system? Do we treat them as system-defined behavior?

1.1.4.10 Q10

Add a bid for Annabel Lee on item 1002, at a price 5 dollars below the current highest bid.

Solution in XQuery: No solution provided.

Expected resulting content of bids.xml: the same as the original contents.

This raises difficulties similar to those seen in Q9. However, Q9 might be addressed by using a different mapping and a schema that spans the data, providing identity contraints. Q10 expresses constraints that can not be expressed in W3C XML Schema. How do we account for such constraints, which may well be implemented in an underlying system? Do we treat them as system-defined behavior?

1.2 Use Case "Address Book" - Synchronizing address book entries

In this scenario, an address book is synchronized among a central archive and two local copies. This scenario is inspired by the Unison file synchronizer. During synchronization, Address book entries with the same name element are considered to be the same entry. The order of entries is irrelevant. For simplicity, we assume that entries may be modified, but not inserted or deleted. When the two copies are synchronized, their state is saved into an archival version. Synchronization is performed as follows:

  • If an entry in one of the two copies is different from the archived one, but the other copy matches the archive, the modified copy is propagated to the archive and to the other copy.

  • If both copies differ from the archive, but they do not both modify the same element in the entry, or they modify the same element but the modified elements have the same value, then the changes from each copy are propagated to both the archive and the other copy.

  • If the copies have each modified the same entry, but modified it in different ways, a problem is reported in the log, and neither the archive nor the copies are changed. (For simplicity, we do not attempt to merge updates.)

1.2.1 Input Data

This section describes the data prior to synchronization.

archive.xml: The central archive, before synchronization.

<archived-agenda>
  <last-synch-time>2005-10-05T10:00</last-synch-time>
  <entry>
    <name>Benjamin</name>
    <contact>benjamin@inria.fr</contact>
  </entry>
  <entry>
    <name>Dario</name>
    <contact>dario@uni-pisa.it</contact>
  </entry>
  <entry>
    <name>Anthony</name>
    <contact>tony@uni-toulon.fr</contact>
  </entry>
</archived-agenda>

                                

log.xml: The central log, before synchronization.

<log>
</log>

                                

copy1.xml: The first modified copy of the address book.

In this copy, Benjamin's contact has changed from INRIA to University of Versailles, Dario has moved from University of Pisa to University of Paris Sud, and Anthony has moved from University of Toulon to the ENA.

<agenda-version>
  <entry>
    <name>Benjamin</name>
    <contact>benjamin@uni-versailles.fr</contact>
  </entry>
  <entry>
    <name>Dario</name>
    <contact>dario@uni-parissud.fr</contact>
  </entry>
  <entry>
    <name>Anthony</name>
    <contact>tony@ena.fr</contact>
  </entry>
</agenda-version>

                                

copy2.xml: The second modified copy of the address book.

In this copy, Benjamin has also moved to University of Versailles, Dario has not moved, and Anthony has moved to the EHESS instead of the ENA:

<agenda-version>  
  <entry>
    <name>Benjamin</name>
    <contact>benjamin@uni-versailles.fr</contact>
  </entry>
  <entry>
    <name>Dario</name>
    <contact>dario@uni-pisa.it</contact>
  </entry>
  <entry>
    <name>Anthony</name>
    <contact>tony@ehess.fr</contact>
  </entry>
 </agenda-version>

                                

1.2.2 Q1

Synchronize the three logs as described in the description of this use case.

Solution in XQuery:

for $a in doc("archive.xml")/entry, 
    $v1 in doc("copy1.xml")/entry, 
    $v2 in doc("copy2.xml")/entry
where $a/name = $v1/name
  and $v1/name = $v2/name
do if ($a/contact = $v1/contact and $v1/contact=$v2/contact)
     then ()
   else if ($v1/contact = $v2/contact)
     then replace value of {$a/contact} with $v1/contact
   else if ($a/contact = $v1/contact)
     then (
       replace value of {$a/contact} with $v2/contact,
       replace value of {$v1/contact} with $v2/contact
     )
   else if ($a/contact = $v2/contact)
     then (
       replace value of {$a/contact} with $v1/contact,
       replace value of {$v2/contact} with $v1/contact
     )
   else (
     insert {
        <fail>
          <arch>{ $a }</arch>
          <v1>{ $v1 }</v1>
          <v2>{ $v2 }</v2>
        </fail>
      }
     as last into doc("log.xml")
   )

  

Expected Results:

Expected results of the agenda synchronization: A synchronization of the two versions of the agenda made on Nov. 9th, 2005, at noon, should have the following impact on the archive, versions, and log.

archive.xml

<archived-agenda>
  <last-synch-time>2005-11-09T12:00</last-synch-time>
  <entry>
    <name>Benjamin</name>
    <!-- copied from the modified entries -->
    <contact>benjamin@uni-versailles.fr</contact>
  </entry>
  <entry>
    <name>Dario</name>
    <!-- copied from first modified version -->
    <contact>dario@uni-parissud.fr</contact>
  </entry>
  <entry>
    <name>Anthony</name>
    <!-- unchanged due to conflict -->
    <contact>tony@uni-toulon.fr</contact>
  </entry>
</archived-agenda>

                                        

log.xml

Note:

In the following XML, the comments were not created by the query, but have been added to explain where each part comes from.

<log>
  <!-- update failure details -->
  <fail>
     <arch>
       <!-- archived agenda version -->
       <entry>
         <name>Anthony</name>
         <contact>tony@uni-toulon.fr</contact>
       </entry>
     </arch>
     <v1>
       <!-- first modified version -->
       <entry>
         <name>Anthony</name>
         <contact>tony@ena.fr</contact>
       </entry>
     </v1>
     <v2>
       <!-- second modified version -->
       <entry>
         <name>Anthony</name>
         <contact>tony@ehess.fr</contact>
       </entry>
     </v2>
  </fail>
</log>

                                

copy1.xml

<agenda-version>
  <entry>
    <name>Benjamin</name>
    <!-- kept after synchronization -->
    <contact>benjamin@uni-versailles.fr</contact>
  </entry>
  <entry>
    <!-- kept after synchronization -->
    <name>Dario</name>
    <contact>dario@uni-parissud.fr</contact>
  </entry>
  <entry>
    <!-- kept after synchronization failure -->
    <name>Anthony</name>
    <contact>tony@ena.fr</contact>
  </entry>
</agenda-version>

                                

copy2.xml

<agenda-version>  
  <entry>
    <!-- kept after synchronization -->
    <name>Benjamin</name>
    <contact>benjamin@uni-versailles.fr</contact>
  </entry>
  <entry>
    <!-- value taken from the other modified version -->
    <name>Dario</name>
    <contact>dario@uni-parissud.fr</contact>
  </entry>
  <entry>
    <!-- kept after synchronization failure -->
    <name>Anthony</name>
    <contact>tony@ehess.fr</contact>
  </entry>
</agenda-version>

                                

1.3 Use Case "SOAP"

This use case processes the message found in Example 1 of the [SOAP Version 1.2 Part 0:Primer] to produce the message found in Example 2. The original message is not modified, but the new message is a modified copy of the original.

1.3.1 Input Data

The input data is taken directly from Example 1 of the [SOAP Version 1.2 Part 0:Primer].

<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> 
 <env:Header>
  <m:reservation xmlns:m="http://travelcompany.example.org/reservation" 
          env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
           env:mustUnderstand="true">
   <m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</m:reference>
   <m:dateAndTime>2001-11-29T13:20:00.000-05:00</m:dateAndTime>
  </m:reservation>
  <n:passenger xmlns:n="http://mycompany.example.com/employees"
          env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
           env:mustUnderstand="true">
   <n:name>Åke Jógvan Øyvind</n:name>
  </n:passenger>
 </env:Header>
 <env:Body>
  <p:itinerary
    xmlns:p="http://travelcompany.example.org/reservation/travel">
   <p:departure>
     <p:departing>New York</p:departing>
     <p:arriving>Los Angeles</p:arriving>
     <p:departureDate>2001-12-14</p:departureDate>
     <p:departureTime>late afternoon</p:departureTime>
     <p:seatPreference>aisle</p:seatPreference>
   </p:departure>
   <p:return>
     <p:departing>Los Angeles</p:departing>
     <p:arriving>New York</p:arriving>
     <p:departureDate>2001-12-20</p:departureDate>
     <p:departureTime>mid-morning</p:departureTime>
     <p:seatPreference/>
   </p:return>
  </p:itinerary>
  <q:lodging
   xmlns:q="http://travelcompany.example.org/reservation/hotels">
   <q:preference>none</q:preference>
  </q:lodging>
 </env:Body>
</env:Envelope>
                                        
                                        

1.3.2 Q1

Check to see if the airports are unambiguously specified in the incoming message. Produce a SOAP response by transforming the incoming message, modifying the time and date to the current time, and replacing the body with a request to clarify which airport should be used for New York City.

Solution in the XQuery Update Facility:

                                        
declare namespace env="http://www.w3.org/2003/05/soap-envelope";
declare namespace m="http://travelcompany.example.org/reservation";
declare namespace n="http://mycompany.example.com/employees";
declare namespace p="http://travelcompany.example.org/reservation/travel";

(:  A clarification is needed only if there are no
 :  airports or more than one for a given city. If
 :  there is precisely one, there is no need to
 :  ask for information on that city.
 :)

declare function local:airportChoices($city as xs:string)
{
  let $airports := collection("airports")/AIRPORTS[CITY = $city]
  return
    if (count($airports) = 0)
    then 
       <error> No airports found for {$city}!</error>
    else if (count($airports) > 1) 
    then 
       <airportChoices>
        { 
          for $c in $airports/CODE
          return (string-value( $c ), " ")
        }
       </airportChoices>
    else ()
};

(:  Make sure that each airport is unambiguous. If there is
 :  more than once airport for a city, ask for clarification.
 :
 :  The primer only shows the error condition, so it is not
 :  clear what to do if there are no errors. Here, we simply
 :  return the airports in the itinerary.
 :)

declare function local:airports($in as element(env:Envelope))
{
    let $departureDeparting := $in//p:departure/p:departing
    let $departureDepartingAirports := collection("airports")/AIRPORTS[CITY = $departureDeparting]
    let $departureArriving := $in//p:departure/p:arriving
    let $departureArrivingAirports := collection("airports")/AIRPORTS[CITY = $departureArriving]
    let $returnDeparting := $in//p:return/p:departing
    let $returnDepartingAirports := collection("airports")/AIRPORTS[CITY = $returnDeparting]
    let $returnArriving := $in//p:return/p:arriving
    let $returnArrivingAirports := collection("airports")/AIRPORTS[CITY = $returnArriving]
    return
       if ( count($departureDepartingAirports)=0 or count($departureDepartingAirports)>1
          or count($departureArrivingAirports)=0 or count($departureArrivingAirports)>1
          or count($returnDepartingAirports)=0 or count($returnDepartingAirports)>1
          or count($returnArrivingAirports)=0 or count($returnArrivingAirports)>1 )
         then
          <p:itineraryClarification>
            { local:airportChoices($departureDeparting) }
            { local:airportChoices($departureArriving) }
            { local:airportChoices($returnDeparting) }
            { local:airportChoices($returnArriving) }
          </p:itineraryClarification>
         else 
          <p:itinerary>
            <p:departure>
              <p:departing>{$departureDeparting}</p:departing>
              <p:arriving>{$departureArriving}</p:arriving>
            </p:departure>
            <p:return>
              <p:departing>{$returnDeparting}</p:departing>
              <p:arriving>{$returnArriving}</p:arriving>
            </p:return>
          </p:itinerary>
};

for $in in $msg/env:Envelope
return
   transform 
     copy $out := $in
     do (
       replace value of {$out//m:dateAndTime} with fn:currentDateTime(),
       replace {$out//env:Body} 
       with <env:Body>
             { local:airports($in) }
            </env:Body>
     )
     return $out
                                        

Expected Result (from [SOAP Version 1.2 Part 0:Primer]):


<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"> 
 <env:Header>
  <m:reservation xmlns:m="http://travelcompany.example.org/reservation" 
      env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
           env:mustUnderstand="true">
   <m:reference>uuid:093a2da1-q345-739r-ba5d-pqff98fe8j7d</m:reference>
   <m:dateAndTime>2001-11-29T13:35:00.000-05:00</m:dateAndTime> 
  </m:reservation>
  <n:passenger xmlns:n="http://mycompany.example.com/employees"
      env:role="http://www.w3.org/2003/05/soap-envelope/role/next"
           env:mustUnderstand="true">
   <n:name>Åke Jógvan Øyvind</n:name>
  </n:passenger>
 </env:Header>
 <env:Body>
  <p:itineraryClarification 
    xmlns:p="http://travelcompany.example.org/reservation/travel">
   <p:departure>
     <p:departing>
       <p:airportChoices>
          JFK LGA EWR 
       </p:airportChoices>
     </p:departing>
   </p:departure>
   <p:return>
     <p:arriving>
       <p:airportChoices>
         JFK LGA EWR 
       </p:airportChoices>
     </p:arriving>
   </p:return>  
  </p:itineraryClarification>
 </env:Body>
</env:Envelope>

A Normative References

XQuery 1.0
World Wide Web Consortium. XQuery 1.0: An XML Query Language. W3C Working Draft, 03 Nov. 2005. See http://www.w3.org/TR/xquery/.
XML Query Use Cases
World Wide Web Consortium. XML Query Use Cases. W3C Working Draft, 15 September 2005. See http://www.w3.org/TR/2005/WD-xquery-use-cases-20050915/.
XQuery Update Facility Requirements
World Wide Web Consortium. XQuery Update Facility Requirements. W3C Working Draft, 3 June 2005. See http://www.w3.org/TR/2005/WD-xquery-update-requirements-20050603/.
XQuery Update Facility
World Wide Web Consortium. XQuery Update Facility. W3C Working Draft, 27 Jan 2005. See http://www.w3.org/TR/2006/WD-xqupdate-20060127/.
SOAP Version 1.2 Part 0:Primer
World Wide Web Consortium. SOAP Version 1.2 Part 0: Primer W3C Recommendation 24 June 2003. See http://www.w3.org/TR/2003/REC-soap12-part0-20030624/.