return to index |
xsdb project page with download links xFeedMe xsdb resources |
This section walks through a number of xsdb use cases, providing examples of database contexts and queries at an informal level.
To understand this section a reader should have some familiarity with XML and common database uses.
The xsdb framework will probably most often be used from within programs using an applications programmer interface (API), but for the purposes of illustration this discussion provides examples using the command line query interface. Most of the examples listed below are also provided as test cases in the xsdbXML/examples subdirectory.
Of course the xsdb framework allows the representation of conventional monolithic first normal form relational tables. For example the "examples/SupplierParts" directory of the distribution includes a representation for C. J. Date's standard Supplier/Parts database.
The supplier table, which lists supplier names, numbers, cities and statuses, is represented in the file "supplier.xsdb" with text
<context> <title>Supplier information</title> <and> <i at="snum">1</i> <s at="sname">Smith</s> <i at="status">20</i> <s at="city">London</s> </and> <and> <i at="snum">2</i> <s at="sname">Jones</s> <i at="status">10</i> <s at="city">Paris</s> </and> <and> <i at="snum">3</i> <s at="sname">Blake</s> <i at="status">30</i> <s at="city">Paris</s> </and> <and> <i at="snum">4</i> <s at="sname">Clark</s> <i at="status">20</i> <s at="city">London</s> </and> <and> <i at="snum">5</i> <s at="sname">Adams</s> <i at="status">30</i> <s at="city">Athens</s> </and> </context>The parts table, which lists part names, numbers, colors, weights and cities, is represented in the file "parts.xsdb" containing text
<context> <title>Parts information</title> <and> <i at="pnum">1</i> <s at="pname">Nut</s> <s at="color">Red</s> <i at="weight">12</i> <s at="pcity">London</s> </and> <and> <i at="pnum">2</i> <s at="pname">Bolt</s> <s at="color">Green</s> <i at="weight">17</i> <s at="pcity">Paris</s> </and> <and> <i at="pnum">3</i> <s at="pname">Screw</s> <s at="color">Blue</s> <i at="weight">17</i> <s at="pcity">Rome</s> </and> <and> <i at="pnum">4</i> <s at="pname">Screw</s> <s at="color">Red</s> <i at="weight">14</i> <s at="pcity">London</s> </and> <and> <i at="pnum">5</i> <s at="pname">Cam</s> <s at="color">Blue</s> <i at="weight">12</i> <s at="pcity">Paris</s> </and> <and> <i at="pnum">6</i> <s at="pname">Cog</s> <s at="color">Red</s> <i at="weight">19</i> <s at="pcity">London</s> </and> </context>The supplierPart table, which lists numbers of suppliers with numbers of parts they supply and the quantity supplied, is represented in the file "SupplierParts.xsdb" with content
<context> <title>The parts supplied by suppliers</title> <and> <i at="snum">1</i> <i at="pnum">1</i> <i at="qty">300</i> </and> <and> <i at="snum">1</i> <i at="pnum">2</i> <i at="qty">200</i> </and> <and> <i at="snum">1</i> <i at="pnum">3</i> <i at="qty">400</i> </and> <and> <i at="snum">1</i> <i at="pnum">4</i> <i at="qty">200</i> </and> <and> <i at="snum">1</i> <i at="pnum">5</i> <i at="qty">100</i> </and> <and> <i at="snum">1</i> <i at="pnum">6</i> <i at="qty">100</i> </and> <and> <i at="snum">2</i> <i at="pnum">1</i> <i at="qty">300</i> </and> <and> <i at="snum">2</i> <i at="pnum">2</i> <i at="qty">400</i> </and> <and> <i at="snum">3</i> <i at="pnum">2</i> <i at="qty">200</i> </and> <and> <i at="snum">4</i> <i at="pnum">2</i> <i at="qty">200</i> </and> <and> <i at="snum">4</i> <i at="pnum">4</i> <i at="qty">300</i> </and> <and> <i at="snum">4</i> <i at="pnum">5</i> <i at="qty">400</i> </and> </context>The following are examples of an xsdb queries against these tables. The first consults the supplier context but keeps only suppliers from London.
<query sort="sname" names="sname snum"> <title>Suppliers from London</title> <and> <s at="city">London</s> <consult href="supplier.xsdb"/> </and> </query>This query run within the "SupplierParts" directory produces the following response:
prompt> query.py supplier_query.xsdb <or> <and> <s at="sname">Clark</s> <i at="snum">4</i> </and> <and> <s at="sname">Smith</s> <i at="snum">1</i> </and> </or>The next query lists part in London but removes any supplied by suppliers from Paris.
<query atts="pname pnum" sort="pname"> <title>Parts in london not supplied by Suppliers from Paris</title> <and> <s at="pcity">London</s> <consult href="parts.xsdb"/> <exclude> <select names="pnum"> <and> <s at="city">Paris</s> <consult href="supplier.xsdb"/> <consult href="supplierParts.xsdb"/> </and> </select> </exclude> </and> </query>This query run within the "SupplierParts" directory produces the following response:
prompt> query.py parts_query.xsdb <or> <and> <s at="pname">Cog</s> <i at="pnum">6</i> </and> <and> <s at="pname">Screw</s> <i at="pnum">4</i> </and> </or> prompt>
Queries may also consult information residing on remote machines delivered via the HTTP protocol. For example the following query uses the copies of the Supplier-Parts tables residing on http://athos.rutgers.edu/~aaron/.
<query names="pname pnum" sort="pname"> <title>Parts in london not supplied by Suppliers from Paris</title> <and> <s at="pcity">London</s> <consult href="http://athos.rutgers.edu/~aaron/parts.xsdb"/> <exclude> <select names="pnum"> <and> <s at="city">Paris</s> <consult href="http://athos.rutgers.edu/~aaron/supplier.xsdb"/> <consult href="http://athos.rutgers.edu/~aaron/supplierParts.xsdb"/> </and> </select> </exclude> </and> </query>When run (from anywhere) the query generates the following response.
prompt>query.py remote_parts_query.xsdb <or> <and> <s at="pname">Cog</s> <i at="pnum">6</i> </and> <and> <s at="pname">Screw</s> <i at="pnum">4</i> </and> </or> prompt>
The xsdb framework also permits expressions which correspond to non-first-normal-form tables -- tables with attributes assigned to complex values. For example the following content of the file "bars1.xsdb" represents bars, sets of drinkers who frequent each bar and sets of beers served by each bar.
<context> <or> <and> <s at="bar">cheers</s> <a at="drinkers"> <or> <s at="drinker">norm</s> <s at="drinker">sam</s> <s at="drinker">woody</s> </or> </a> <a at="serves"> <or> <and><s at="beer">bud</s> <i at="qty">500</i></and> <and><s at="beer">samaddams</s> <i at="qty">255</i></and> </or> </a> </and> <and> <s at="bar">frankies</s> <a at="drinkers"> <s at="drinker">pierre</s> </a> <a at="serves"> <and><s at="beer">snafu</s> <i at="qty">5</i></and> </a> </and> <and> <s at="bar">joes</s> <a at="drinkers"> <or> <s at="drinker">norm</s> <s at="drinker">wilt</s> </or> </a> <a at="serves"> <or> <and><s at="beer">bud</s> <i at="qty">217</i></and> <and><s at="beer">mickies</s> <i at="qty">2222</i></and> <and><s at="beer">samaddams</s> <i at="qty">13</i></and> </or> </a> </and> <and> <s at="bar">winkos</s> <a at="drinkers"> <nothing/> <!-- no drinkers --> </a> <a at="serves"> <and><s at="beer">rollingrock</s> <i at="qty">432</i></and> </a> </and> <and> <s at="bar">lolas</s> <a at="drinkers"> <or> <s at="drinker">adam</s> <s at="drinker">lola</s> <s at="drinker">norm</s> <s at="drinker">woody</s> </or> </a> <a at="serves"> <or> <and><s at="beer">mickies</s> <i at="qty">1515</i></and> <and><s at="beer">pabst</s> <i at="qty">333</i></and> </or> </a> </and> </or> </context>For example the last entry indicates that the bar lolas is frequented by adam, lola, norm, and woody, and lolas serves the beers mickies and pabst. The following query against this table uses the "ungroup" operation to normalize the drinkers.
<query> <title>bars frequented by norm</title> <select names="bar"> <and> <ungroup at="drinkers"> <consult href="bars1.xsdb"/> </ungroup> <s at="drinker">norm</s> </and> </select> </query>The result of this query is
<or> <s at="bar">cheers</s> <s at="bar">lolas</s> <s at="bar">joes</s> </or>Another query might not ungroup the drinkers in order to compute aggregate information about the drinkers.
<query> <title>bars and the number of drinkers for that bar</title> <select names="bar ndrinkers"> <and> <consult href="bars1.xsdb"/> <calc at="ndrinkers" expr="count(drinkers.drinker)"/> </and> </select> </query>The response to this query would be
<or> <and> <s at="bar">cheers</s> <i at="ndrinkers">3</i> </and> <and> <s at="bar">lolas</s> <i at="ndrinkers">4</i> </and> <and> <s at="bar">frankies</s> <i at="ndrinkers">1</i> </and> <and> <s at="bar">winkos</s> <i at="ndrinkers">0</i> </and> <and> <s at="bar">joes</s> <i at="ndrinkers">2</i> </and> </or>In addition to the "a" tag which identifies a complex value and the "ungroup" operation which normalizes a complex value, xsdb provides the "group" and "subquery" operations which construct complex values.
The xsdb framework allows tabular data to be partitioned horizontally (by rows) or vertically (by columns) or by a combination of horizontal and vertical partitioning as demonstrated by the following example.
Ken wants to sell some books which he lists in a simple xsdb file
Ken/BooksForSale.xsdbFor simplicity we assume this file resides on a local filesystem, accessed directly, but it could also be on a remote computer served using HTTP. Suppose the file contains the following
<context > <title>Ken's books for sale</title> <or> <and> <id at="ISBN">0-13-041801</id> <f at="asking">5.0</f> </and> <and> <id at="ISBN">0-596-00132-0</id> <f at="asking">2.0</f> </and> <and> <id at="ISBN">0-596-00292-0</id> <f at="asking">5.0</f> </and> </or> </context>Which reads that the book with ISBN 0-013-041801 may be purchased for 5 dollars, or the book with ISBN 0-596-00132-0 may be purchased for 2 dollars or the book with ISBN 0-596-00292-0 may be purchased for 5 dollars.
A simple query against this database might attempt to look up an offer to sell the book with ISBN 0-596-00053-7 using the syntax
<query> <title>Ken's offers for 0-596-00053-7</title> <and> <id at="ISBN">0-596-00053-7</id> <consult href="./Ken/BooksForSale.xsdb"/> </and> </query>This query reads approximately "in the context of BooksForSale.xsdb tell me about listings with ISBN 0-596-00053-7." Because there is no such ISBN in the database the response would be
<nothing />Meaning that no such book is for sale with that ISBN in this context.
Another simple query might ask for a book which is in the database using the syntax
<query> <title>Ken's offers for 0-596-00053-0</title> <and> <id at="ISBN">0-596-00132-0</id> <consult href="./Ken/BooksForSale.xsdb"/> </and> </query>The response to this query would read
<and > <id at="ISBN">0-596-00132-0</id> <f at="asking">2.0</f> </and>Meaning that the BooksForSale.xsdb context is asking 2 dollars for the book with ISBN 0-596-00132-0.
Ken decides to get together with Jake and Wilma to publish the books they want to sell in a single place. To allow Jake and Wilma to easily retain control of their own lists Ken creates the database file
./AllBooksForSale.xsdbwith content
<context> <title>All books for sale</title> <and> <!-- books for sale by ken, jake, or wilma all priced in US$ --> <s at="currency">US Dollars</s> <or> <!-- ken's books in BooksForSale.xsdb --> <consult href="Ken/BooksForSale.xsdb"> <s at="email">ken@smegu.edu</s> </consult> <!-- jakes's books in his space --> <consult href="Jake/BooksForSale.xsdb"> <s at="email">jake@smegu.edu</s> </consult> <!-- wilma's books in her space --> <consult href="Wilma/BooksForSale.xsdb"> <s at="email">wilma@smegu.edu</s> </consult> </or> <!-- get info about titles and ISBNs from isbn database --> <consult href="isbn/db.xsdb"/> </and> </context>The intended reading of this expression is as follows. To correlate book Titles with ISBNs consult the http://www.isbn.org/db.xsdb database. The intended units for currency are US Dollars. Furthermore there are three places to look for information on books for sale: books for sale with contact email ken@smegu.edu are listed in "./Ken/BooksForSale.xsdb", books for contact email jake@smegu.edu are listed in "./Jake/BooksForSale.xsdb", and finally books with contact email wilma@smegu.edu are listed in "./Wilma/BooksForSale.xsdb".
If wilma is also offering to sell the book with ISBN 0-586-00132-0 the query
<query> <title>learning perl for sale</title> <and> <consult href="AllBooksForSale.xsdb"/> <s at="Title">Learning Perl</s> </and> </query>might evaluate to
<or> <and> <id at="ISBN">0-596-00132-0</id> <s at="Title">Learning Perl</s> <f at="asking">12.0</f> <s at="currency">US Dollars</s> <s at="email">wilma@smegu.edu</s> </and> <and> <id at="ISBN">0-596-00132-0</id> <s at="Title">Learning Perl</s> <f at="asking">2.0</f> <s at="currency">US Dollars</s> <s at="email">ken@smegu.edu</s> </and> </or>Meaning that ken is offering to sell Learning Perl for 2 dollars whereas wilma is offering to sell it for 12 dollars.
Nicky has a collection of small prime numbers and wishes to offer the list as a queriable database by grouping them into files. The first file primes.xsdb lists the first 10 primes and indicates to look to the next file primesGT29.xsdb for primes larger than 29.
<context> <title>Primes</title> <or> <i at="N">2</i> <i at="N">3</i> <i at="N">5</i> <i at="N">7</i> <i at="N">11</i> <i at="N">13</i> <i at="N">17</i> <i at="N">19</i> <i at="N">23</i> <i at="N">29</i> <consult href="./primesGT29.xsdb"> <i at="N"><gt>29</gt></i> </consult> </or> </context>The file primesGT29.xsdb in turn contains the next 10 primes with a consultation indicating to refer to the next file primesGT71.xsdb for primes larger than 71
<context> <title>Primes greater than 29</title> <or> <i at="N">31</i> <i at="N">37</i> <i at="N">41</i> <i at="N">43</i> <i at="N">47</i> <i at="N">53</i> <i at="N">59</i> <i at="N">61</i> <i at="N">67</i> <i at="N">71</i> <consult href="./primesGT71.xsdb"> <i at="N"><gt>71</gt></i> </consult> </or> </context>The files continue in this manner (primesGT113.xsdb, primesGT173.xsdb, primesGT229.xsdb, primesGT281.xsdb, primesGT349.xsdb, primesGT409.xsdb) until the file primesGT463.xsdb. Since the last prime Nicky knows is 467 the final file primesGT463.xsdb contains the assertion
<context> <title>Primes greater than 463</title> <or> <i at="N">467</i> <i at="N" weak="true"><gt>467</gt></i> </or> </context>Which reads roughly: 467 is a prime and if there are any primes larger than 467 I don't know what they are (or I refuse to tell you).
Note that in place of static files listing primes these assertions could be generated dynamically by a program which could generate the list of primes requested when the query arrives.
Suppose we wanted the answer to the question: "from the sequence 43 45 47 49 which are not primes?"
<query> <!-- which are the non-primes? --> <and> <exclude> <consult href="http://nickysbox.toster.com/primes.xsdb"/> </exclude> <or> <i at="N">43</i> <i at="N">45</i> <i at="N">47</i> <i at="N">49</i> </or> </and> </query>The response to this query would be
<or> <i at="N">45</i> <i at="N">49</i> </or>