Professional Documents
Culture Documents
NET
Table of Contents
Introduction
This tutorial will introduce you to XQuery and help you how to use it in ASP.NET.
It starts with explaining what XQuery is and its purpose besides current query languages like
XPath and XSLT.
Then we'll move on to look at some simple XQuery Expressions. We'll see how they are
constructed and what results they should obtain given an example XML source document. We'll
see that these expressions are extremely readable and easy to write.
You will be able to play with XQuery Expressions yourself, using a simple ASP.NET C# Web
Application. It is assumed that you know the basics of how to use VS.NET (creating a new
project, adding references to a project, programming in code-behind mode, etc.).
What is XQuery?
XQuery is a new XML Query Language, which is a work in progress by the XML Query
Working Group of the W3C. It has currently the W3C Working Draft status, but is due to reach
W3C Recommendation status before the end of this year.
Where does XQuery stand in the jungle of XML related languages? Well, we could visualize this
roughly as follows (note that no complete overview is pretended, for the sake of simplicity):
XSL 1.0
XSL-FO
XML
Schema
In the above diagram we see some specifications above the dashed line - these are W3C
Recommendations. The specifications below the dashed line are currently what the W3C calls
"Works in Progress"; as you can see, XQuery is one of them. Furthermore, we see that XPath 1.0
first was a part of XSL 1.0 but grew out later on as a fully separate specification. The main
reason for that is that XPath is being reused in other W3C specifications.
XQuery is a strongly typed language, and its data type system is based on XML Schema
(http://www.w3.org/XML/Schema).
It is also tightly related to XPath 2.0: XQuery is actually a superset of XPath 2.0. XPath 2.0 is
also used by the upcoming XSLT 2.0 specification, which means that XSLT 2.0 will also be a
superset of XPath 2.0. Whereas XSLT is a transforming language and is single document based,
XQuery is more a querying language, which is multiple document based and is more suitable for
big XML source documents. In the end, both will co-exist, and each one will cover different
areas of possible applications, but also will share some overlap in certain areas, of course.
XQuery will have support for updating the data source, whether it is a file on disk, or a database
table. It will use a SQL-like syntax for doing this. This support could still be integrated in the
first upcoming W3C Recommendation, but it is more likely that it will be postponed to a later
version, as there are still many issues to resolve.
You can read up more detailed on the subject at: http://www.w3.org/XML/Query. If you intend
to do this, the first document you should read is "XQuery 1.0: An XML Query Language",
available at: http://www.w3.org/TR/xquery/. That document will give you a general idea what
XQuery has to offer without going into too much detail.
XQuery is basically a set of XQuery Expression types, which make up a query. We'll see some
basic examples of them a bit later on. From now on, in the context of this tutorial, let's call an
XQuery Expression simply an xquery.
To run an xquery in ASP.NET, you need at least an XML source document, be it a file on disk,
or a dynamically generated one. The important thing to remember here is that the XML source
needs to be well formed. Valid is not required here, but you could always validate the XML prior
to applying it an xquery, of course. Then, you would need to write your xquery to run over one
or more input XML source documents.
To augment your understanding of how it all works, let us now first see what exactly is MS
XQuery Demo before we move on to creating a test page in ASP.NET and run some basic
xqueries.
MS XQuery Demo
As said, the implementation that Microsoft developed is called MS XQuery Demo, and can be
found at http://xqueryservices.com. MS XQuery Demo basically consists of two parts.
One is the web site demo test page. You can use this page to interactively test your xqueries. The
xqueries are run over fixed XML source documents – they are not modifiable.
The other part, which we are going to use here, is a downloadable managed .NET class set. Now,
go ahead, and download and install this first; you can get it at
http://xqueryservices.com/Setup/xquery.msi.
This managed class set let's you run your xqueries over your own XML source documents, be it
one single document, or multiple ones.
XQuery's relation with System.Xml
The MS XQuery managed classes reside in the namespace Microsoft.Xml.XQuery. They are
designed for use with the existing classes in the System.Xml namespace.
XQueryDocument
XQueryNavigator
XQueryNavigatorCollection
XML XQueryExpression
source
document
XQueryException XQueryNavigator
.ToXML()
The XQueryExpression contains the xquery. This xquery defines the target navigators to run the
xquery over, as we'll see later on in the example section.
But first, to be able to run xqueries, in the next section we'll be creating a simple xquery tester,
which later is used to run various xqueries over a basic and simple XML source document, to
show you a series of basic xqueries.
Creating the project is simple. Start VS.NET and click the New Project link on the start page.
Choose Visual C# Projects, and in the right pane, choose ASP.NET Web Application. Enter its
name, "XQueryTester". Click OK and wait until the classes are created.
Then, delete "WebForm1.aspx" and add the page "XQT.aspx" from the download material (note
that if you're not using VS's Solution Explorer to do this you also need to copy the
"XQT.aspx.cs" file).
Then, add a Reference to the project by choosing the menu "Poject | Add Reference". In the
.NET tab, select the file named "Microsoft.Xml.XQuery.dll", and click the button "Select".
Finally, click OK. The reference should appear in the Solution Explorer, under the References
directory. Press Ctrl+Alt+L if you do not see the Solution Explorer.
Next, add a new project subdirectory called "xsl", and add the file "xqt.xsl". This is the XSL
Stylesheet that is used to format the xquery results.
You'll need to choose a Start Up file before compiling and running your application. Choose "Set
as Start Up Page" on "XQT.aspx" by right-clicking the project name in the Solution Explorer
window pane, and then finally press F5. After compiling the project, and activating the
debugging environment, the following screen should turn up:
OK, now you should be able to enter your XML source, and run some simple xqueries over it.
The next section will guide you in doing that, and will give you a good feeling of what XQuery
can do and how you should write xqueries. After having run some xqueries using some of the
most important XQuery Expression types, you'll quickly get the hang of constructing simple
xqueries.
Then, after that section is over, we'll be looking in detail at how the code behind the web form
works.
The XML source file we'll use throughout this section of the tutorial is as follows:
<root>
<tutorials>
<tutorial category="basic">
<id>T000001</id>
<title>Introduction to XQuery</title>
<paragraph>
<subtitle>Introduction</subtitle>
<text>XQuery is an XML query language.</text>
</paragraph>
<paragraph>
<subtitle>Body</subtitle>
<text>XQuery has a pleasant to use syntax.
The human-readable form is actually not XML, but it does produce XML,
if properly written.The language has a host of expression types, called
XQuery Expressions.
One of the most powerful XQuery Expression is called the FLWR
(pronounced 'flower') expression.</text>
</paragraph>
<paragraph>
<subtitle>Resumen</subtitle>
<text>XQuery is new and complete XML querying language, likely to get
very popular in the coming years.</text>
</paragraph>
</tutorial>
<tutorial category="intermediate">
<id>T000002</id>
<title>XQuery's Syntax</title>
<paragraph>
<subtitle>Introduction</subtitle>
<text>XQuery has two syntax forms: one is the human-readable called
XQuery, the other one is its XML counterpart and is called XQueryX.</text>
</paragraph>
<paragraph>
<subtitle>Body</subtitle>
<text>In this tutorial we'll only look closer at the human-readable
version of XQuery.
It is called human-readable because it is designed to be highly
readable by humans, and is easy to write.
The language consists basically of a set of expression types.</text>
</paragraph>
<paragraph>
<subtitle>Resumen</subtitle>
<text>In this tutorial we had a closer look at the human-readable
syntax form of XQuery.</text>
</paragraph>
</tutorial>
<tutorial category="advanced">
<id>T000003</id>
<title>XQuery: Advanced Tricks</title>
<paragraph>
<subtitle>Introduction</subtitle>
<text>In this section we'll talk about some advanced XQuery
tricks.</text>
</paragraph>
<paragraph>
<subtitle>Body</subtitle>
<text>The first advanced trick we'll look at is the use of nested
FLWR expressions.
You can compare this with a relational database query where you use
the UNION keyword to combine results from tables in one resulting
table.</text>
</paragraph>
<paragraph>
<subtitle>Resumen</subtitle>
<text>XQuery allows for some cool and advanced querying tricks.</text>
</paragraph>
</tutorial>
</tutorials>
</root>
Note that the used XSL Stylesheet to present the resulting XML was originally written by Jason
Patterson at SnippetCentral at TopXML.com
(http://www.topxml.com/snippetcentral/main.asp?
view=viewsnippet&lang=&id=v20010305161458). All the credit of this very useful script goes
to him. The script used in this tutorial is an updated version he personally sent me, and is not
modified by me in any way. Jason also indicated that he's going to update the site's script real
soon, which is great news – it may already be there when you read this.
The stylesheet is as follows:
<xsl:text> </xsl:text>
<font
style="{$template-style}{$attr-name-style}">
<xsl:text>xmlns</xsl:text>
<xsl:if
test="string-length(name())>0"><xsl:text>:</xsl:text></xsl:if>
<xsl:value-
of select="name()"/>
</font>
<font
style="{$template-style}{$punctuation-style}">
<xsl:text>="</xsl:text>
</font>
<font
style="{$template-style}{$attr-value-style}">
<xsl:value-of
select="."/>
</font>
<font
style="{$template-style}{$punctuation-style}">
<xsl:text>"</xsl:text>
</font>
</xsl:if>
</xsl:for-each>
</xsl:if>
</font>
<xsl:choose>
<xsl:when test="count(node()) = 0">
<font style="{$template-style}
{$punctuation-style}">
<xsl:text>/></xsl:text>
</font>
</xsl:when>
<xsl:otherwise>
<font style="{$template-style}
{$punctuation-style}">
<xsl:text>></xsl:text>
</font>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
<xsl:for-each select="$selnode/node()">
<xsl:call-template name="formatxml">
<xsl:with-param name="selnode" select="."/>
<xsl:with-param name="indent"
select="concat(number('2'),'em;')"/>
</xsl:call-template>
</xsl:for-each>
<xsl:choose>
<xsl:when test="self::text()"/>
<xsl:when test="count(node()) = 0"/>
<xsl:otherwise>
<font style="{$template-style}{$punctuation-
style}">
<xsl:text></</xsl:text>
</font>
<font style="{$template-style}{$node-name-
style}">
<xsl:value-of select="name($selnode)"/>
</font>
<font style="{$template-style}{$punctuation-
style}">
<xsl:text>></xsl:text>
</font>
</xsl:otherwise>
</xsl:choose>
</div>
</xsl:template>
<xsl:template name="html-replace-entities">
<xsl:param name="text"/>
<xsl:variable name="tmp">
<xsl:call-template name="replace-substring">
<xsl:with-param name="from" select="'>'"/>
<xsl:with-param name="to" select="'&gt;'"/>
<xsl:with-param name="value">
<xsl:call-template name="replace-substring">
<xsl:with-param name="from"
select="'<'"/>
<xsl:with-param name="to"
select="'&lt;'"/>
<xsl:with-param name="value">
<xsl:call-template name="replace-
substring">
<xsl:with-param name="from"
select="'"'"/>
<xsl:with-param name="to"
select="'&quot;'"/>
<xsl:with-param name="value">
<xsl:call-template
name="replace-substring">
<xsl:with-param
name="from" select="concat('&','apos;')"/>
<xsl:with-param
name="to" select="'&apos;'"/>
<xsl:with-param
name="value">
<xsl:call-
template name="replace-substring">
This human-readable version consists of a set of powerful expressions. So, what kind of
expressions does XQuery offer? Let's have a look at the following list first and then continue
with some simple examples of the most important ones:
Primary Expressions
No examples are included here since these expressions are in fact the building blocks for use in
all other XQuery Expression types that follow.
Path Expressions
Path Expressions This type of expression is used to locate nodes in a given tree
or XML document. You can use either relative or absolute
(rooted) path expressions. Relative path expressions are used
in context with the current node.
Expression: Example(s):
Path 1. document("xqt")
Expressions
In this first example (which is by default shown when the application is
run), the output is simply the same as your input XML. The
document() function is used here to access the XML source as an
XQuery navigator collection, in which each navigator has its own name –
in this case, "xqt". We'll see more of this when we come to look at the
code later on in this tutorial.
<?xml version="1.0"?>
<root>
<title>Introduction to XQuery</title>
<title>XQuery's Syntax</title>
<title>XQuery: Advanced Tricks</title>
</root>
Here, the path expression selects every title that can be found in the XML
source.
3. <root>
{ document("xqt")//title/text() }
</root>
<?xml version="1.0"?>
<root>Introduction to XQueryXQuery's
SyntaxXQuery: Advanced Tricks</root>
Here, the xquery is neatly formatted, but that does not influence the
output in any way – it is just for readability and easy writing.
In this case, the values of the four found titles are concatenated into one
string here (on one line) because the path expression contains text().
Note that whitespace or other special characters (like returns and
linefeeds) located outside the element nodes are not outputted by the XSL
processor.
To show one more screenshot of XQueryTester in action, the output of the second example is
shown on the screen like this:
You can see that the output is nicely colored and indented, just like IE does. This cool look is
due to Jason Patterson's stylesheet.
Sequence Expressions
Expression: Example(s):
Sequence 1. <seq> { (1,6,3) } </seq>
Expressions
The output of this xquery is:
<?xml version="1.0"?>
<seq>163</seq>
Arithmetic Expressions
Expression: Example(s):
Arithmetic 1. <sum> { 1 + 2 } </sum>
Expressions
Output shown:
<?xml version="1.0"?>
<sum>3</sum>
Comparison Expressions
Comparison Expressions This group of expressions are used to compare two values.
XQuery supports four types of comparison expressions:
value comparisons, general comparisons, node comparisons,
and order comparisons.
Expression: Example(s):
Comparison 1. <compare>
Expressions {
IF 3 > 2
THEN <yes/>
ELSE <no/>
}
</compare>
<?xml version="1.0"?>
<compare>
<yes/>
</compare>
Logical Expressions
Logical Expressions This group contains the 'AND' and the 'OR' expression.
Expression: Example(s):
Logical 1. <logical>
Expressions {
IF (3 > 2) AND (2 != 4)
THEN <yes/>
ELSE <no/>
}
</logical>
<?xml version="1.0"?>
<logical>
<yes/>
</logical>
Constructors
Expression: Example(s):
Constructors 1. <root>
<tutorial>
<title>XQuery Explained</title>
</tutorial>
</root>
This produces the following output, which is fully self-explanatory:
<?xml version="1.0"?>
<root>
<tutorial>
<title>XQuery Explained</title>
</tutorial>
</root>
FLWR Expressions
Expression: Example(s):
FLWR 1. <root>
Expressions {
FOR $a IN document("xqt")//tutorials
RETURN $a/tutorial/title
}
</root>
<?xml version="1.0"?>
<root>
<title>Introduction to XQuery</title>
<title>XQuery's Syntax</title>
<title>XQuery: Advanced Tricks</title>
</root>
This xquery is exactly the same as the second example in the Path
Expression example section above. This time however, we can use the
FLWR Expression type to create very powerful xqueries. Let's look at a
second example to see how.
2. <root>
{
FOR $a IN document("xqt")//tutorials
RETURN
<tutorial>
{
FOR $b IN document("xqt")//tutorials
WHERE $a = $b
RETURN $b/tutorial/id
}
</tutorial>
}
</root>
<?xml version="1.0"?>
<root>
<tutorial>
<id>T000001</id>
<id>T000002</id>
<id>T000003</id>
</tutorial>
</root>
Sorting Expressions
Sorting Expressions This type of expressions is used when the order of a sequence
has to be changed. It is basically done using the SORTBY
clause.
Expression: Example(s):
Sorting 1. <root>
Expressions {
LET $a := document("xqt")//tutorial/title
RETURN $a SORTBY (title)
}
</root>
This xquery first assigns the variable $a all the available titles, returns
them, and sorts them in ascending (which is the default) order. The
output generated cannot be verified using MS XQuery Demo, because the
SORTBY clause is still not supported; you can check that by running the
xquery but without the bolded "SORTBY (title)". If it was
supported, the output should resemble the following:
<?xml version="1.0"?>
<root>
<title>Introduction to XQuery</title>
<title>XQuery's Syntax</title>
<title>XQuery: Advanced Tricks</title>
</root>
Conditional Expressions
Conditional Expressions XQuery has only support for the if – then – else conditional
expression. It uses a Test Expression, which determines
whether to go into the then, or the else expression.
Expression: Example(s):
Conditional 1. <root>
Expressions {
IF document("xqt")//title/text()="xxx"
THEN <true/>
ELSE <false/>
}
</root>
<?xml version="1.0"?>
<root>
<FALSE/>
</root>
Note that the value 'false' (which is a string) is returned as the boolean
value 'FALSE'.
2. <root>
{
IF document("xqt")//title/text()
="Introduction to XQuery"
THEN <true/>
ELSE <false/>
}
</root>
<?xml version="1.0"?>
<root>
<TRUE/>
</root>
As with the first example, the returned boolean value is 'TRUE' and not
the string 'true'.
Quantified Expressions
Expression: Example(s):
Quantified 1. SOME $a IN document("xqt")//tutorials
Expressions SATISFIES $a/tutorial/title
Expressions on Datatypes
Expressions on Datatypes This group is used when working with sequence types and
includes the Instanceof Expression, the Typeswitch
Expression, the CaseClause Expression, and the Cast
Expression.
Validate Expressions
Expression: Example(s):
Validate <root>
Expressions {
LET $a := validate{1,2,3,4,5}
RETURN $a
}
</root>
Code explanation
Well, now that we've seen some interesting simple xqueries and got a chance to play with them,
it is time to have a closer look at the code used to get the XQueryTester to work in ASP.NET.
The code for the whole page is shown first. Then we'll take out the bold parts, which are code
fragments that have been added after the automatic code generation that VS.NET does for us
when we add a new page to the project.
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
// added namespaces
using System.Xml;
using Microsoft.Xml.XQuery;
namespace XQueryTester
{
/// <summary>
/// Summary description for XQT.
/// </summary>
public class XQT : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Label lblXMLsource;
protected System.Web.UI.WebControls.Label lblXQuery;
protected System.Web.UI.WebControls.Label lblResult;
protected System.Web.UI.WebControls.TextBox txtXMLsource;
protected System.Web.UI.WebControls.TextBox txtXQueryExpr;
protected System.Web.UI.WebControls.Xml Xml1;
protected System.Web.UI.WebControls.Button btnExecXQuery;
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnExecXQuery.Click += new System.EventHandler _
(this.btnExecXQuery_Click);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
First, we need to add the following namespaces to be able to use the System.Xml and the
Microsoft.Xml.XQuery namespace:
using System.Xml;
using Microsoft.Xml.XQuery;
Then, when we add user controls to the page, and when we do, the following lines are added
automatically:
As you can see, three Label controls, two Textbox controls, one Xml Web Server control, and
one Button control were placed on the Web Form.
Then, the following event handler was automatically generated for us when double-clicking the
button "Execute XQuery" to add the code behind it:
The code for the button in question is the last code that was added to the page and is as follows:
In the next three lines, a new XmlDocument object is created. This object is used to load the XML
source taken from the textbox "txtXMLsource" as a string. Once loaded, the
CreateNavigator() method creates a navigator which is added to the
XQueryNavigatorCollection object:
The next step is to create the XQuery Expression. This is first written or copied into the textbox
"txtXQueryExpr" and then fed as a parameter into a new object of type XQueryExpression. This
loads, parses and compiles the expression string into a valid XQuery Expression. It is here that
syntax errors and not yet implemented language features are caught and reported back at run-
time.
Then, we'll need a new XQueryNavigator object to execute the xquery we just have created and
run it against the navigator(s) we have created in our navigator collection object. To do this, we
must use the Execute() method:
XQueryNavigator nav;
nav = expr.Execute(navCol);
Now that we have the result of the xquery in XML format, we need a way to present this to the
user in a more human-readable form. First, we'll need another object to be able to pass the XML
result. The XmlDocument object allows for this:
The final step is to assign the XML result to the XML Web Server Control and apply it an XSLT
using an XSL stylesheet called "xqt.xsl":
Xml1.Document = doc2;
Xml1.TransformSource = "xsl\\xqt.xsl";
Wrap-up
In this tutorial, we have seen what XQuery is, and how it is supported in the .NET Framework.
We have built a simple XQueryTester application, which enabled us to run some basic xqueries
over a single XML input source document.
This tutorial enables you to go further in-depth. For example, a good topic to investigate from
this point would be to develop a new application, which makes use of more than one
XQueryNavigator. For example, you could create a new XQueryNavigator for each of the tables
you need to query, and then run nested FLWR xqueries over it, just like you would do using
SQL.
*****
* Rights Reserved © Pieter Siegers 2003 *
*