| Grainger Connect | Table of contents | Indexes | Unlocking the Web's Full Potential with XML and Directory Services | |||
Durham ![]() Robie, Jonathan ![]() Software AG ![]() USA ![]() | Jonathan Robie |
| R&D Fellow |
| Software AG |
| 3207 Gibson Road
Durham
(North Carolina)
USA
(27703)
Email: jonathan.robie@sagus.com |
| Biography |
Introduction |
Binding and Constructing: XML-QL |
<?xml version="1.0"?> <!DOCTYPE bib SYSTEM "books.dtd"> <bib> <book year="1955"> <title>Harold and the Purple Crayon</title> <author> <last>Johnson</last> <first>Crockett</first> </author> <publisher>Harper and Row</publisher> <price>$4.76</price> </book> <book year="1956"> <title>Harold's Fairy Tale</title> <author> <last>Johnson</last> <first>Crockett</first> </author> <publisher>Harper and Row</publisher> <price>$4.76</price> </book> </bib> |
<results>
<result>
<author>
<last>Johnson</last>
<first>Crockett</first>
</author>
</result>
</results>
|
| This query is not possible in XQL, which insists on producing one <author/> element in the output for each <author/> found in the input. In XML-QL, this is a straightforward query: |
CONSTRUCT <results> {
WHERE
<bib>
<book>
<author><firstname>$f</firstname><lastname>$l</lastname></author>
</book>
</bib> IN "http://www.bn.com/bib.xml"
CONSTRUCT
<result>
<author><firstname>$f</firstname><lastname>$l</lastname></author>
</result>
} </results>
|
| Now let's modify this query to list each author, then list each title of a book written by that author. The output of our query should look like this: |
<results>
<result>
<author>
<last>Johnson</last>
<first>Crockett</first>
</author>
<title>Harold and the Purple Crayon</title>
<title>Harold's Fairy Tale</title>
</result>
</results>
|
| This requires a more complex query: |
CONSTRUCT <results> {
WHERE
<bib>
<book>
<author><last>$l</last><first>$f</first></author>
</book>
</bib> IN "http://www.bn.com/bib.xml"
CONSTRUCT
<result>
<author><last>$l</last><first>$f</first></author>
{
WHERE
<bib>
<book>
<title>$t</title> // join on $l and $f
<author><last>$l</last><first>$f</first></author>
</book>
</bib> IN "http://www.bn.com/bib.xml"
CONSTRUCT <title>$t</title>
}
</result>
} </results> |
Projecting from the Document: XQL |
<xql:result>
<bib>
<book>
<title>Harold and the Purple Crayon</title>
<author>
<last>Johnson</last>
<first>Crockett</first>
</author>
</book>
<book>
<title>Harold's Fairy Tale</title>
<author>
<last>Johnson</last>
<first>Crockett</first>
</author>
</book>
</bib>
</xql:result> |
| Here is the XQL query that was used to produce the above results: |
document("http://www.bn.com")/bib {
book {
title | author
}
} |
| The corresponding XML-QL query is much more complicated, using a nested query to preserve the nested structure of the original: |
CONSTRUCT <bib> {
WHERE
<bib>
<book>
<title>$t</title>
</book> CONTENT_AS $b
</bib> IN "www.bn.com/bib.xml"
CONSTRUCT
<book>
<title>$t</title>
{ WHERE <author>$a</author> IN $b
CONSTRUCT <author>$a</>
}
</book>
} </bib>
|
<Chapter><Title>Desserts</Title>
<Para>This chapter tells you all about yummy desserts.</Para>
<Section><Title>Cookies</Title>
<Para>Cookies are flat things that sometimes have chocolate chips.</Para>
</Section>
<Section><Title>Candy</Title>
<Para>Candy is dandy.</Para>
</Section>
<Section><Title>Pies and Tarts</Title>
<Para>Pies and tarts are even better.</Para>
</Section>
<Section><Title>Cakes, Tortes, and Cupcakes</Title>
<Para>Cakes, Tortes, and Cupcakes are absolutely awesome.</Para>
</Section>
</Chapter> |
<xql:result>
<Chapter><Title>Desserts</Title>
<Section><Title>Cookies</Title>
</Section>
<Section><Title>Candy</Title>
</Section>
<Section><Title>Pies and Tarts</Title>
</Section>
<Section><Title>Cakes, Tortes, and Cupcakes</Title>
</Section>
</Chapter>
</xql:result> |
| Here is the XQL query that generates the above results: |
//(Chapter | Section | Chapter/Title | Section/Title) |
<section><section.title>Procedure</section.title> The patient was taken to the operating room where she was placed in supine position and <Anesthesia>induced under general anesthesia.</Anesthesia> <Prep> <action>Foley catheter was placed to decompress the bladder</action> and the abdomen was then prepped and draped in sterile fashion. </Prep> <paragraph /> <Incision> A curvilinear incision was made <Geography>in the midline immediately infraumbilical</Geography> and the subcutaneous tissue was divided <Instrument>using electrocautery.</Instrument> </Incision> The fascia was identified and <action>#2 0 Maxon stay sutures were placed on each side of the midline.</action> <Incision> The fascia was divided using <Instrument>electrocautery</Instrument> and the peritoneum was entered. </Incision> <Observation>The small bowel was identified</Observation> and <action> the <Instrument>Hasson trocar</Instrument> was placed under direct visualization. </action> <action> The <Instrument>trocar</Instrument> was secured to the fascia using the stay sutures </action> <!-- The section continues, but we excerpt it here... --> |
//section[section.title="Procedure"][not(.//Anaesthesia before .//Incision)] |
| Fortunately, no such procedures are found in the above data. Similarly, we may wish to know what actions were made after the first incision but before the second incision. Here is the XQL query: |
//section[section.title="Procedure"]//((action after Incision[1]) before Incision[2]) |
| Here are the results returned by that query: |
<xql:result> <action>#2 0 Maxon stay sutures were placed on each side of the midline.</action> </xql:result> |
The Best of Both Worlds |
Grouping by Value |
| Many of the queries that are possible in XML-QL but not in XQL involve grouping results by value. For instance, consider this XML-QL query, taken directly from the section on XML-QL: |
CONSTRUCT <bib> {
WHERE
<bib>
<book>
<author>$a</author>
</book>
</bib> IN "http://www.bn.com/bib.xml"
CONSTRUCT
<book>
<author>$a</author>
</book>
} </bib>
|
| XQL can easily search for all <author/> elements within a data source: |
document("http://www.bn.com/bib.xml")/bib/book/author |
document("http://www.bn.com/bib.xml")/bib {
book {
for ($a := author) {
make_element("author") { $a }
}
}
} |
| Naturally, for() can be nested: |
document("http://www.bn.com/bib.xml")/bib {
book {
for ($a := author) {
for ($t := title) {
make_element("result") { $a, $t }
}
}
}
} |
Simplifying Element Creation |
document("http://www.bn.com/bib.xml")/bib{
for ($b := book) {
for ($t := title) {
for ($a := author) {
<book> {
<author> { $a } | <title> { $t }
}
}
}
}
} |
| In character-challenged environments, "{[" is used as a synonym for "<", and "]}" is used as a synonym for ">": |
document("http://www.bn.com/bib.xml")/bib{
for ($b := book) {
for ($t := title) {
for ($a := author) {
{[book]} {
{[author]} { $a } | {[title]} { $t }
}
}
}
}
} |
<HTML>
<HEAD> {
<TITLE> {
"Books"
}
}
<BODY> {
<TABLE> {
document("http://www.bn.com/bib.xml")/bib/book {
for-each($a, author)
for-each($t, title) {
<TR> {
<TD> { $a }
<TD> { $t }
}
}
}
}
}
} |
Variables and Joins |
document("http://www.bn.com/bib.xml")/bib/book {
for ($i := isbn) {
title | author
| document("http://www.amazon.com/reviews.xml")/reviews/entry[isbn=$i]
| document("http://www.bookfinders.com/listings.xml")[dealers/books/book[isbn=$i]]
}
}
|
<results> {
document("http://www.bn.com/bib.xml")
/bib/book/author/<result> {
for ($l, last) { for ($f, first) { <author><last>$l</last><first>$f</first></author>
document("http://www.bn.com/bib.xml")
/bib/book[author/last=$l and author/first=$f]/title }
}
}
} |
Links |
<?xml version="1.0"?> <!DOCTYPE bib SYSTEM "books.dtd"> <bib> <book year="1955"> <title>Harold and the Purple Crayon</title> <author HREF="http://www.biblio.com/~jcrockett/books.xml"> <last>Johnson</last> <first>Crockett</first> </author> <publisher>Harper and Row</publisher> <price>$4.76</price> </book> </bib> |
| Now let's use document() to return the complete list of books by the author of "Harold and the Purple Crayon", as listed in the document to which the hyperlink points: |
document("http://www.bn.com/bib.xml")
//author[title="Harold and the Purple Crayon"] {
document(@HREF)//title
} |
Sorting |
| A sorting operator allows values in a sequence to be sorted. The following query sorts books by title and the last name of the first author: |
document("http://www.bn.com/bib.xml")/bib {
book sortby title, author[0]/last
} |
| The following example also lists books, sorted by title, with only the title and the author in the results. Authors are sorted by their last and first names: |
document("http://www.bn.com/bib.xml")/bib {
book {
title,
author sortby last, first
} sortby title
} |
Conclusion |
Bibliography |
| Grainger Connect | Table of contents | Indexes | Unlocking the Web's Full Potential with XML and Directory Services | |||