XSLT 2.0 and Beyond


XSLT 2.0 and Beyond

Elliotte Rusty Harold

Software Development 2002 West

Friday, March 26, 2002

elharo@metalab.unc.edu

http://www.cafeconleche.org//


Outline


XPath 2.0


XPath 2.0 Goals


XPath 2.0 Requirements


XPath 1.0 Data Model

(Adapted from Jeni Tennison)


XPath 2.0 Data Model

(Adapted from Jeni Tennison)


XPath Comments

<xsl:apply-templates 
 select="{-- The difference between the context node and the 
             current node is crucial here --}
 ../composition[@composer=current()/@id]"/>

Namespace wildcards

<xsl:template match="*:set">
  This matches MathML set elements, SVG set elements, set
  elements in no namespace at all, etc. 
</xsl:template>

Can use functions as location steps


Can use parenthesized expressions as location steps


Dereference steps


Constructing sequences


Sequence example

<?xml version="1.0"?> 
<xsl:stylesheet version="2.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/">
    <numbers>
      <xsl:for-each select="(1 to 10)">
        <integer>
          <xsl:value-of select="."/>
        </integer>
      </xsl:for-each>
    </numbers>
  </xsl:template>

</xsl:stylesheet>

Output (modulo white space):

<?xml version="1.0" encoding="utf-8"?>
<numbers>
<integer>1</integer>
<integer>2</integer>
<integer>3</integer>
<integer>4</integer>
<integer>5</integer>
<integer>6</integer>
<integer>7</integer>
<integer>8</integer>
<integer>9</integer>
<integer>10</integer>
</numbers>

Unions of sequences

<?xml version="1.0"?> 
<xsl:stylesheet version="2.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output indent="yes"/>             
                
  <xsl:template match="/">
    <numbers>
      <xsl:for-each select='(3 to 10) | (5 to 12) | (20 to 23)'>
        <integer>
          <xsl:value-of select="."/>
        </integer>
      </xsl:for-each>
    </numbers>
  </xsl:template>

</xsl:stylesheet>

Output:

<numbers>
<integer>3</integer>
<integer>4</integer>
<integer>5</integer>
<integer>6</integer>
<integer>7</integer>
<integer>8</integer>
<integer>9</integer>
<integer>10</integer>
<integer>11</integer>
<integer>12</integer>
<integer>20</integer>
<integer>21</integer>
<integer>22</integer>
<integer>23</integer>
</numbers>

Intersections of sequences

<?xml version="1.0"?> 
<xsl:stylesheet version="2.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output indent="yes"/>             
                
  <xsl:template match="/">
    <numbers>
      <xsl:for-each select='(3 to 10) intersect (5 to 12)'>
        <integer>
          <xsl:value-of select="."/>
        </integer>
      </xsl:for-each>
    </numbers>
  </xsl:template>

</xsl:stylesheet>

Output:

<numbers>
<integer>5</integer>
<integer>6</integer>
<integer>7</integer>
<integer>8</integer>
<integer>9</integer>
<integer>10</integer>
</numbers>

Except sequences

<?xml version="1.0"?> 
<xsl:stylesheet version="2.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output indent="yes"/>             
                
  <xsl:template match="/">
    <numbers>
      <xsl:for-each select='(3 to 10) except (5 to 12)'>
        <integer>
          <xsl:value-of select="."/>
        </integer>
      </xsl:for-each>
    </numbers>
  </xsl:template>

</xsl:stylesheet>

Output:

<numbers>
  <integer>3</integer>
  <integer>4</integer>
</numbers>

Value comparison operators


General comparisons


Node comparisons


For Expressions


for Example

Consider the list of weblogs at http://static.userland.com/weblogMonitor/logs.xml

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE foo SYSTEM "http://msdn.microsoft.com/xml/general/htmlentities.dtd">
<weblogs>
    <log>
        <name>MozillaZine</name>
        <url>http://www.mozillazine.org</url>
        <changesUrl>http://www.mozillazine.org/contents.rdf</changesUrl>
        <ownerName>Jason Kersey</ownerName>
        <ownerEmail>kerz@en.com</ownerEmail>
        <description>THE source for news on the Mozilla Organization.  DevChats, Reviews, Chats, Builds, Demos, Screenshots, and more.</description>
        <imageUrl></imageUrl>
        <adImageUrl>http://static.userland.com/weblogMonitor/ads/kerz@en.com.gif</adImageUrl>
    </log>
    <log>
        <name>SalonHerringWiredFool</name>
        <url>http://www.salonherringwiredfool.com/</url>
        <ownerName>Some Random Herring</ownerName>
        <ownerEmail>salonfool@wiredherring.com</ownerEmail>
        <description></description>
    </log>
    <log>
        <name>SlashDot.Org</name>
        <url>http://www.slashdot.org/</url>
        <ownerName>Simply a friend</ownerName>
        <ownerEmail>afriendofweblogs@weblogs.com</ownerEmail>
        <description>News for Nerds, Stuff that Matters.</description>
    </log>
</weblogs>

The changesUrl element points to a document like this:

<?xml version="1.0"?>
<!DOCTYPE rss PUBLIC "-//Netscape Communications//DTD RSS 0.91//EN" 
                     "http://my.netscape.com/publish/formats/rss-0.91.dtd">
<rss version="0.91">
  <channel>
    <title>MozillaZine</title>
    <link>http://www.mozillazine.org/</link>
    <language>en-us</language>
    <description>Your source for Mozilla news, advocacy, interviews, builds, and more!</description>
    <copyright>Copyright 1998-2002, The MozillaZine Organization</copyright>
    <managingEditor>jason@mozillazine.org</managingEditor>
    <webMaster>jason@mozillazine.org</webMaster>
    <image>
      <title>MozillaZine</title>
      <url>http://www.mozillazine.org/image/mynetscape88.gif</url>
      <description>Your source for Mozilla news, advocacy, interviews, builds, and more!</description>
      <link>http://www.mozillazine.org/</link>
    </image>

    <item>
      <title>BugDays Are Back!</title>
      <link>http://www.mozillazine.org/talkback.html?article=2151</link>
    </item>

    <item>
      <title>Independent Status Reports</title>
      <link>http://www.mozillazine.org/talkback.html?article=2150</link>
    </item>

  </channel>

</rss>

We want to process all the item elements from each weblog.


for Example

<xsl:template match="weblogs">
  <xsl:apply-templates select="
    for $url in log/changesUrl
    return document($url)/item
  "/>
</xsl:template>

Conditional Expressions

Not all weblogs have a changesUrl

<xsl:template match="log">
  <xsl:apply-templates select="
    if (changesUrl)
     then document(changesUrl)
     else document(url)"/>
</xsl:template>

Quantified Expressions

<xsl:template match="weblogs">
  <xsl:if test="some $log in log satisfies changesURL">
     ????
  </xsl:if>
</xsl:template>

<xsl:template match="weblogs">
  <xsl:if test="every $log in log satisfies url">
    ????
  </xsl:if>
</xsl:template>

Functions and operators


Accessor Functions

xf:node-kind(Node)
Returns a string identifying the kind of node; i.e. "document", "element", "attribute", "text", "namespace", "processing-instruction", or "comment".
xf:name(Node)
returns zero or one QName
xf:string(Object)
returns the string value of anything
xf:data(Node)
returns a sequence of zero or more typed simple values
xf:base-uri(node)
returns the base URI of an Element or Document node
xf:unique-ID(element)
returns the unique ID of an element

Constructor Functions


Arithmetic operators


Numeric comparison operators


Numeric Functions


String functions


Regular expressions


Boolean Functions


Date and time functions


Qualified Name Functions


Binary operators


Node Functions and Operators


Sequence Functions


Context Functions


Casting Functions


XSLT 2.0


XSLT 2.0 Goals


XSLT 2.0 Non-goals


XSLT 2.0 Requirements


Some specific improvements that are likely


Identifying 2.0 stylesheets

<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <!-- Top level elements -->

</xsl:stylesheet>

No result tree fragments


xsl:for-each-group


Grouping example: input


Grouping example: desired output

<?xml version="1.0"?>
<forwardslash>

<section>
  <title>developers</title>
<story>
<title>ROX Desktop Update</title>
<url>http://slashdot.org/article.pl?sid=02/02/18/180240</url>
<time>2002-02-18 18:50:13</time>
<author>timothy</author>
<department>small-simple-swift</department>
<topic>104</topic>
<comments>32</comments>
<image>topicx.jpg</image>
</story>

</section>

<section>
  <title>articles</title>

<story>
<title>HP Selling Systems With Linux</title>
<url>http://slashdot.org/article.pl?sid=02/02/18/1712241</url>
<time>2002-02-18 17:37:20</time>
<author>timothy</author>
<department>wish-this-wasn't-remarkable</department>
<topic>173</topic>
<comments>188</comments>
<image>topichp.gif</image>
</story>

<story>
<title>Excellent Hacks to the ReplayTV 4000</title>
<url>http://slashdot.org/article.pl?sid=02/02/18/1619213</url>
<time>2002-02-18 16:46:04</time>
<author>CmdrTaco</author>
<department>hardware-I-lust-after</department>
<topic>129</topic>
<comments>117</comments>
<image>topictv.jpg</image>
</story>

<story>
<title>Peek-a-Boo(ty)</title>
<url>http://slashdot.org/article.pl?sid=02/02/18/1546226</url>
<time>2002-02-18 15:58:06</time>
<author>Hemos</author>
<department>pirate-treasure</department>
<topic>158</topic>
<comments>207</comments>
<image>topicprivacy.gif</image>
</story>

<story>
<title>Self-Shredding E-Mail</title>
<url>http://slashdot.org/article.pl?sid=02/02/18/1343202</url>
<time>2002-02-18 14:37:45</time>
<author>timothy</author>
<department>plausible-deniability</department>
<topic>158</topic>
<comments>170</comments>
<image>topicprivacy.gif</image>
</story>

<story>
<title>CIA &amp;amp; KGB Gadgets On Display</title>
<url>http://slashdot.org/article.pl?sid=02/02/18/0252219</url>
<time>2002-02-18 13:52:04</time>
<author>Hemos</author>
<department>looking-a-tthe-gear</department>
<topic>126</topic>
<comments>103</comments>
<image>topictech2.gif</image>
</story>


<story>
<title>How to Fix the Unix Configuration Nightmare</title>
<url>http://slashdot.org/article.pl?sid=02/02/18/0248248</url>
<time>2002-02-18 10:48:36</time>
<author>Hemos</author>
<department>fixing-the-problem</department>
<topic>130</topic>
<comments>367</comments>
<image>topicunix.jpg</image>
</story>


</section>
<section>
  <title>science</title>


<story>
<title>Re-Building the Wright Flyer</title>
<url>http://slashdot.org/article.pl?sid=02/02/18/060257</url>
<time>2002-02-18 12:29:12</time>
<author>timothy</author>
<department>we-hope-they-wear-modern-helmets</department>
<topic>126</topic>
<comments>132</comments>
<image>topictech2.gif</image>
</story>


<story>
<title>Sleep Less, Live Longer</title>
<url>http://slashdot.org/article.pl?sid=02/02/18/0511253</url>
<time>2002-02-18 07:38:15</time>
<author>timothy</author>
<department>if-you're-reading-this</department>
<topic>134</topic>
<comments>309</comments>
<section>science</section>
<image>topicscience.gif</image>
</story>

<story>
<title>Warming and Slowing the World</title>
<url>http://slashdot.org/article.pl?sid=02/02/18/0243253</url>
<time>2002-02-18 04:39:39</time>
<author>Hemos</author>
<department>slowing-things-down</department>
<topic>134</topic>
<comments>312</comments>
<section>science</section>
<image>topicscience.gif</image>
</story>

</section>

</forwardslash>

Grouping example: stylesheet

<?xml version="1.0"?> 
<xsl:stylesheet version="2.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/">
    <forwardslash>
      <xsl:apply-templates select="*"/>
    </forwardslash>
  </xsl:template>

  <xsl:template match="backslash">
    <xsl:for-each-group select="story" group-by="section">
      <section>
        <title><xsl:value-of select="current-group()/section"/></title>
        <xsl:apply-templates select="."/>
      </section>
    </xsl:for-each-group>
  </xsl:template>

  <xsl:template match="story">
    <story>
      <xsl:apply-templates/>
    </story>
  </xsl:template>

  <xsl:template match="*">
    <xsl:copy-of select="."/>
  </xsl:template>

  <xsl:template match="section"/>

</xsl:stylesheet>

xsl:destination


xsl:result-document


xsl:result-document Example

     <xsl:output name="ccl:html" method="html" encoding="ISO-8859-1" />

     <xsl:result-document href="index.html" format="ccl:html">
       <html>
         <head>
           <title><xsl:value-of select="title"/></title>         
         </head>
         <body> 
           <h1 align="center"><xsl:value-of select="title"/></h1> 
           <ul>
             <xsl:for-each select="slide">
               <li><a href="{format-number(position(),'00')}.html"><xsl:value-of select="title"/></a></li>
             </xsl:for-each>    
           </ul>           
           
           <p><a href="{translate(title,' ', '_')}.html">Entire Presentation as Single File</a></p>
              
           <hr/>
           <div align="center">
             <A HREF="01.html">Start</A> | <A HREF="/xml/">Cafe con Leche</A>
           </div>
           <hr/>
           <font size="-1">
              Copyright 2002 
              <a href="http://www.elharo.com/">Elliotte Rusty Harold</a><br/>       
              <a href="mailto:elharo@metalab.unc.edu">elharo@metalab.unc.edu</a><br/>
              Last Modified <xsl:apply-templates select="last_modified" mode="lm"/>
           </font>
         </body>     
       </html>     
     </xsl:result-document>  

Sorting

<xsl:sort-key
  name = "Qualified Name">
  <!-- Content: (xsl:sort+) -->
</xsl:sort-key>

xsl:namespace

<xsl:namespace name="xsd">http://www.w3.org/2001/XMLSchema</xsl:namespace>


Value of a sequence

<x><xsl:value-of select="(1,2,3,4)" separator=" | "/></x>

<x>1 | 2 | 3 | 4</x>


default-xpath-namespace


An XSLT 1.0 stylesheet for working with XHTML

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns="http://www.w3.org/1999/xhtml" 
  xmlns:html="http://www.w3.org/1999/xhtml" 
>

  <xsl:output method="html" encoding="ISO-8859-1"/>

  <xsl:template match="week">
    <html xml:lang="en" lang="en">
      <head><title><xsl:value-of select="//html:h1[1]"/></title></head>
      <body bgcolor="#ffffff" text="#000000">

        <xsl:apply-templates select="html:body"/>

        <font size="-1">Last Modified Mon June 5, 2001<br />
          Copyright 2001 Elliotte Rusty Harold<br />
          <a href="mailto:elharo@metalab.unc.edu">elharo@metalab.unc.edu</a>
        </font>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="html:body">
    <xsl:apply-templates 
      select="text()[count(following-sibling::html:hr)>1]|*[count(following-sibling::html:hr)>1]" />

    <hr/>
  </xsl:template>

  <xsl:template match="html:*">
    <xsl:copy>
      <xsl:for-each select="@*">
        <xsl:copy-of select="."/>
      </xsl:for-each>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="html:font[@size='-1']"></xsl:template>

  <xsl:template match="html:a">
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="html:applet">
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="html:param"/>

</xsl:stylesheet>

An XSLT 2.0 stylesheet for working with XHTML

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns="http://www.w3.org/1999/xhtml" 
  default-xpath-namespace="http://www.w3.org/1999/xhtml"
>

  <xsl:output method="html" encoding="ISO-8859-1"/>

  <xsl:template match="week">
    <html xml:lang="en" lang="en">
      <head><title><xsl:value-of select="//h1[1]"/></title></head>
      <body bgcolor="#ffffff" text="#000000">

        <xsl:apply-templates select="body"/>

        <font size="-1">Last Modified Mon June 5, 2001<br />
          Copyright 2001 Elliotte Rusty Harold<br />
          <a href="mailto:elharo@metalab.unc.edu">elharo@metalab.unc.edu</a>
        </font>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="body">
    <xsl:apply-templates 
     select="text()[count(following-sibling::hr)>1]|*[count(following-sibling::hr)>1]"/>

    <hr/>
  </xsl:template>

  <xsl:template match="*">
    <xsl:copy>
      <xsl:for-each select="@*">
        <xsl:copy-of select="."/>
      </xsl:for-each>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="font[@size='-1']"></xsl:template>

  <xsl:template match="a">
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="applet">
    <xsl:apply-templates/>
  </xsl:template>

  <xsl:template match="param"/>

</xsl:stylesheet>

User defined data elements


Typed variables and parameters


Functions defined in XSLT

<xsl:function name="math:factorial"
 xmlns:fib="http://www.example.com/math"
 exclude-result-prefixes="math">
  <xsl:param name="index" type="xsd:nonNegativeInteger"/>
  <xsl:result type="xsd:positiveInteger"
    select="if ($sentence eq 0) then 1
            else math:factorial(index - 1)/>
</xsl:function>

Including text files

For example,

<include_as_text source="bib.xml"/>

<xsl:template match="include_as_text">
  <xsl:value-of select="unparsed-text(@source)"/>
</xsl:template>

XQuery

Three parts:


XQuery Language


Documents to Query


Physical Representations to Query


Where is XQuery used?


The XML Model vs. the Relational Model

A relational database contains tables An XML database contains collections
A relational table contains records with the same schema A collection contains XML documents with the same DTD
A relational record is an unordered list of named values An XML document is a tree of nodes
A SQL query returns an unordered set of records An XQuery returns an unordered sequence of nodes

Query Data Types


An example document to query

Most of the examples in this talk query this bibliography document at the (relative) URL bib.xml:

<bib>
<book year="1994">
<title>TCP/IP Illustrated</title>
<author><last>Stevens</last><first>W.</first></author>
<publisher>Addison-Wesley</publisher>
<price> 65.95</price>
</book>

<book year="1992">
<title>Advanced Programming in the Unix Environment</title>
<author><last>Stevens</last><first>W.</first></author>
<publisher>Addison-Wesley</publisher>
<price>65.95</price>
</book>

<book year="2000">
<title>Data on the Web</title>
<author><last>Abiteboul</last><first>Serge</first></author>
<author><last>Buneman</last><first>Peter</first></author>
<author><last>Suciu</last><first>Dan</first></author>
<publisher>Morgan Kaufmann Publishers</publisher>
<price> 39.95</price>
</book>

<book year="1999">
<title>The Economics of Technology and Content for Digital TV</title>
<editor>
<last>Gerbarg</last><first>Darcy</first>
<affiliation>CITI</affiliation>
</editor>
<publisher>Kluwer Academic Publishers</publisher>
<price>129.95</price>
</book>

</bib>

Adapted from Mary Fernandez, Jerome Simeon, and Phil Wadler: XML Query Languages: Experiences and Exemplars, 1999, as adapted in XML Query Use Cases


The XQuery FLWR


Query: List titles of all books

   FOR $t IN document("bib.xml")/bib/book/title
   RETURN
      $t 

Adapted from XML Query Use Cases


Query Result: Book Titles

  <title>TCP/IP Illustrated</title>
  <title>Advanced Programming in the Unix Environment</title>
  <title>Data on the Web</title>
  <title>The Economics of Technology and Content for Digital TV</title>
 

Adapted from XML Query Use Cases


XQueryX


Element Constructors

List titles of all books in a bib element. Put each title in a book element.

<bib>
  {
   FOR $t IN document("bib.xml")/bib/book/title
   RETURN
    <book>
     { $t }
    </book>
  }
</bib>

Adapted from XML Query Use Cases


Query Result: Book Titles

<bib>
  <book>
    <title>TCP/IP Illustrated</title>
  </book>
  <book>
    <title>Advanced Programming in the Unix Environment</title>
  </book>
  <book>
    <title>Data on the Web</title>
  </book>
  <book>
    <title>The Economics of Technology and Content for Digital TV</title>
  </book>
</bib>
 

Adapted from XML Query Use Cases


Query with WHERE

Adapted from XML Query Use Cases


Query Result: Titles of books published by Addison-Wesley

<bib>
    <title>TCP/IP Illustrated</title>
    <title>Advanced Programming in the Unix Environment</title>
</bib>
 

Adapted from XML Query Use Cases


Query with Booleans

Adapted from XML Query Use Cases


Query Result: books published by Addison-Wesley after 1993

<bib>
    <title>Advanced Programming in the Unix Environment</title>
</bib>
 

Adapted from XML Query Use Cases


Attribute Constructors

Adapted from XML Query Use Cases


Query Result: books published by Addison-Wesley after 1993, including their year and title.

<bib>
  <book year="1992">
    <title>Advanced Programming in the Unix Environment</title>
  </book>
</bib>
 

Adapted from XML Query Use Cases


Query with multiple variables

Create a list of all the title-author pairs, with each pair enclosed in a result element.

<results>
 {
   FOR $b IN document("bib.xml")/bib/book,
     $t IN $b/title,
     $a IN $b/author
   RETURN
    <result>
    { $t }
    { $a }
    </result>
  }
</results>

Adapted from XML Query Use Cases


Query Result: A list of all the title-author pairs

<results>
    <result>
         <title>TCP/IP Illustrated</title>
         <author><last>Stevens</last><first>W.</first></author>
    </result>
    <result>
         <title>Advanced Programming in the Unix Environment</title>
         <author><last>Stevens</last><first>W.</first></author>
    </result>
    <result>
         <title>Data on the Web</title>
         <author><last>Abiteboul</last><first>Serge</first></author>
    </result>
    <result>
         <title> Data on the Web</title>
         <author><last>Buneman</last><first>Peter</first></author>
    </result>
    <result>
         <title>Data on the Web</title>
         <author><last>Suciu</last><first>Dan</first></author>
    </result>
</results>
 

Adapted from XML Query Use Cases


Nested Queries

For each book in the bibliography, list the title and authors, grouped inside a result element.

<results>
 {
   FOR $b IN document("bib.xml")/bib/book
   RETURN
    <result>
     { $b/title }
     {  
       FOR $a IN $b/author
       RETURN $a
     }
    </result>
 }
</results>

Adapted from XML Query Use Cases


Query Result: A list of the title and authors of each book in the bibliography

<?xml version="1.0"?>
<results xmlns:ino="http://namespaces.softwareag.com/tamino/response2" xmlns:xql="http://metalab.unc.edu/xql/">
  <result>
    <title>TCP/IP Illustrated</title>
    <author>
      <last>Stevens</last>
      <first>W.</first>
    </author>
  </result>
  <result>
    <title>Advanced Programming in the Unix Environment</title>
    <author>
      <last>Stevens</last>
      <first>W.</first>
    </author>
  </result>
  <result>
    <title>Data on the Web</title>
    <author>
      <last>Abiteboul</last>
      <first>Serge</first>
    </author>
    <author>
      <last>Buneman</last>
      <first>Peter</first>
    </author>
    <author>
      <last>Suciu</last>
      <first>Dan</first>
    </author>
  </result>
  <result>
    <title>The Economics of Technology and Content for Digital TV</title>
  </result>
</results> 

Adapted from XML Query Use Cases


Query with distinct

For each author in the bibliography, list the author's name and the titles of all books by that author, grouped inside a result element.

<results>
 {
   FOR $a IN distinct-values(document("bib.xml")//author)
   RETURN
    <result>
     { $a }
     {  FOR $b IN document("bib.xml")/bib/book[author=$a]
        RETURN $b/title
     }
    </result>
 }
</results>

Adapted from XML Query Use Cases


Query Result

<results>
  <result>
    <author><last>Stevens</last><first>W.</first></author>
    <title>TCP/IP Illustrated</title>
    <title>Advanced Programming in the Unix Environment</title>
  </result>

  <result>
    <author><last>Abiteboul</last><first>Serge</first></author>
    <title>Data on the Web</title>
  </result>

  <result>
    <author><last>Buneman</last><first>Peter</first></author>
    <title>Data on the Web</title>
  </result>

  <result>
    <author><last>Suciu</last><first>Dan</first></author>
      <title>Data on the Web</title>
  </result>
</results>
 

Adapted from XML Query Use Cases


Query with sorting

List the titles and years of all books published by Addison-Wesley after 1991, in alphabetic order.

<bib>
 {
   FOR $b IN document("bib.xml")//book
    [publisher = "Addison-Wesley" AND @year > "1991"]
   RETURN
    <book>
     { $b/@year } { $b/title }
    </book> SORTBY (title)
 }
</bib>

Adapted from XML Query Use Cases


Query Result

<bib>
  <book year="1992">
    <title>Advanced Programming in the Unix Environment</title>
  </book>
  <book year="1994">
    <title>TCP/IP Illustrated</title>
   </book>
</bib>
  

Adapted from XML Query Use Cases


Queries with functions

Adapted from XML Query Use Cases


Query Result

<result>
 <book>
  <title> Data on the Web </title>
  <author> <last> Suciu </last> <first> Dan </first> </author>
 </book>
</result>

Adapted from XML Query Use Cases


A different document about books

Sample data at "reviews.xml":

<reviews>
  <entry>
    <title>Data on the Web</title>
    <price>34.95</price>
    <review>
       A very good discussion of semi-structured database
       systems and XML.
    </review>
  </entry>
  <entry>
    <title>Advanced Programming in the Unix Environment</title>
    <price>65.95</price>
    <review>
      A clear and detailed discussion of UNIX programming.
    </review>
  </entry>
  <entry>
    <title>TCP/IP Illustrated</title>
    <price>65.95</price>
    <review>
      One of the best books on TCP/IP.
    </review>
  </entry>
</reviews>

Adapted from XML Query Use Cases


This document uses a different DTD

<!ELEMENT reviews (entry*)>
<!ELEMENT entry   (title, price, review)>
<!ELEMENT title   (#PCDATA)>
<!ELEMENT price   (#PCDATA)>
<!ELEMENT review  (#PCDATA)>

Query that joins two documents

For each book found in both bib.xml and reveiws.xml, list the title of the book and its price from each source.

<books-with-prices>
 {
   FOR $b IN document("bib.xml")//book,
     $a IN document("reviews.xml")//entry
   WHERE $b/title = $a/title
   RETURN
    <book-with-prices>
     { $b/title },
       <price-amazon> { $a/price/text() } </price-amazon>
       <price-bn> { $b/price/text() } </price-bn>
    </book-with-prices>
 }
</books-with-prices>

Adapted from XML Query Use Cases


Result

<books-with-prices>
  <book-with-prices>
    <title>TCP/IP Illustrated</title>
    <price-amazon>65.95</price-amazon>
    <price-bn>65.95</price-bn>
  </book-with-prices>

  <book-with-prices>
    <title>Advanced Programming in the Unix Environment</title>
    <price-amazon>65.95</price-amazon>
    <price-bn>65.95</price-bn>
  </book-with-prices>

  <book-with-prices>
    <title>Data on the Web</title>
    <price-amazon>34.95</price-amazon>
    <price-bn>39.95</price-bn>
  </book-with-prices>
</books-with-prices>
  

Adapted from XML Query Use Cases


prices.xml Query Sample Data

The next query also uses an input document named "prices.xml":

<prices>
  <book>
    <title>Advanced Programming in the Unix Environment</title>
    <source>www.amazon.com</source>
    <price>65.95</price>
  </book>
  <book>
    <title>Advanced Programming in the Unix Environment </title>
    <source>www.bn.com</source>
    <price>65.95</price>
  </book>
  <book>
    <title>TCP/IP Illustrated </title>
    <source>www.amazon.com</source>
    <price>65.95</price>
  </book>
  <book>
    <title>TCP/IP Illustrated </title>
    <source>www.bn.com</source>
    <price>65.95</price>
  </book>
  <book>
    <title>Data on the Web</title>
    <source>www.amazon.com</source>
    <price>34.95</price>
  </book>
  <book>
    <title>Data on the Web</title>
    <source>www.bn.com</source>
    <price>39.95</price>
  </book>
</prices>


Adapted from XML Query Use Cases


Query with reused variables

<results>
 {
   FOR $t IN distinct(document("prices.xml")/book/title)
   LET $p := $doc/book[title = $t]/price
   RETURN
    <minprice title = { $t/text() } >
     { min($p) }
    </minprice>
 }
</results>

Adapted from XML Query Use Cases


Query Result

<results>
  <minprice title="Advanced Programming in the Unix Environment"> 65.95 </minprice>
  <minprice title="TCP/IP Illustrated"> 65.95 </minprice>
  <minprice title="Data on the Web"> 34.95 </minprice>
</results>   

Adapted from XML Query Use Cases


Multiple FLWR Queries

<bib>
 {
   FOR $b IN document("bib.xml")//book[author]
   RETURN
    <book>
     { $b/title }
     { $b/author }
    </book>,
   FOR $b IN document("bib.xml")//book[editor]
   RETURN
    <reference>
     { $b/title }
     <org> { $b/editor/affiliation/text() } </org>
    </reference>
 }
</bib>

Adapted from XML Query Use Cases


Query Result

<bib>
    <book>
         <title>TCP/IP Illustrated</title>
         <author><last> Stevens </last> <first> W.</first></author>
    </book>

    <book>
         <title>Advanced Programming in the Unix Environment</title>
         <author><last>Stevens</last><first>W.</first></author>
    </book>

    <book>
         <title>Data on the Web</title>
         <author><last>Abiteboul</last><first>Serge</first></author>
         <author><last>Buneman</last><first>Peter</first></author>
         <author><last>Suciu</last><first>Dan</first></author>
    </book>

    <reference>
        <title>The Economics of Technology and Content for Digital TV</title>
        <org>CITI</org>
    </reference>
</bib>

Adapted from XML Query Use Cases


Query Software


What's the difference between XQuery and XSLT?


To Learn More


Index | Cafe con Leche

Copyright 2002 Elliotte Rusty Harold
elharo@metalab.unc.edu
Last Modified February 22, 2002