Tutorial: Using XQuery in ASP.NET
XQuery's relation with System.Xml
The XQueryNavigatorCollection class
Building and running the application
Worksheet 1: Path Expression
examples
Worksheet 2: Sequence Expression
examples
Worksheet 3: Arithmetic Expression
examples
Worksheet 4: Comparison Expression
examples
Worksheet 5: Logical Expression
examples
Worksheet 6: Constructor examples
Worksheet 7: FLWR Expression
examples
Worksheet 8: Sorting Expression
examples
Worksheet 9: Conditional Expression
examples
Worksheet 10: Quantified Expression
examples
Worksheet 11: Expression on
Datatypes examples
Worksheet 12: Validate Expression
examples
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.).
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):




Fig. 1: XQuery's relation to other W3C XML related specifications
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.
As you may know, ASP.NET basically has the System.Xml namespace supporting the use of XML in .NET code. The MS XQuery Demo managed class set adds the capability to use XQuery in conjunction with System.Xml and other .NET classes. We'll go into this early XQuery implementation a bit further on.
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.
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.
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.
The managed classes in MS XQuery are: XQueryNavigator, XQueryDocument, XQueryNavigatorCollection, XQueryExpression, and XQueryException. Let's have a look at each one of them now.
|
XQueryNavigator |
This class is used to create an XML object for navigation. |
|
XQueryDocument |
This class provides an XML object to run xqueries over. |
|
XQueryNavigatorCollection |
A collection of XQueryNavigator objects to run xqueries over. |
|
XQueryExpression |
This class provides an object, which encapsulates the XQuery Expression – it is parsed, checked for any syntax error, and finally compiled. Then it is ready to be run over the navigator collection of XQueryNavigators. |
|
XQueryException |
This class provides for any exception thrown by the XQuery classes. |
The classes needed to run an xquery are basically XQueryNavigator, XQueryNavigatorCollection, and XQueryExpression. How they interrelate can best be shown as follows:


![]()
Fig. 2: MS XQuery Demo managed class set
In the above diagram we see that the XQueryNavigatorCollection is a collection of XQueryNavigator classes. Each XQueryNavigator represents a set of data. We'll call them simply navigators here.
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.
In this section, we'll create a simple ASP.NET web form letting the user cut and paste their XML source in a textbox, and then copy and paste the xquery and run it using the MS XQuery .NET Managed class set. The resulting output is shown using the XML Web Control, after having it applied an XSL Stylesheet, to display the results in a more neat and readable XML format.
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:

Fig. 3: Screenshot of XQueryTester's opening window
If you run into trouble, try re-reading the section to see if you didn't miss something. If you do not succeed in getting the project to work, you can try to copy the whole project from the download material to your web root, activate the web application using the Internet Services Manager (ISM), and run the application. You may need to change the web root if yours is different, and also the reference may need to be added again if the path is incorrect.
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:
<?xml version="1.0"
encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl"
href="test.xsl"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output
omit-xml-declaration="yes" method="xml"/>
<xsl:param
name="includexml" select="'yes'" />
<xsl:template
match="/">
<blockquote>
<xsl:if
test="$includexml = 'yes'">
<font
style="color:green;font:10pt 'Verdana';">
<xsl:text><?xml
version="1.0"?></xsl:text>
</font>
</xsl:if>
<xsl:for-each
select="node()">
<xsl:call-template
name="formatxml">
<xsl:with-param
name="selnode" select="."/>
</xsl:call-template>
</xsl:for-each>
</blockquote>
</xsl:template>
<xsl:template
name="formatxml">
<xsl:param
name="selnode"/>
<xsl:param
name="template-style">font:10pt 'Verdana';</xsl:param>
<xsl:param
name="indent">0em;</xsl:param>
<xsl:param
name="punctuation-style">color:blue;</xsl:param>
<xsl:param
name="node-name-style">color:#990000;</xsl:param>
<xsl:param
name="comment-style">color:gray;</xsl:param>
<xsl:param
name="pi-style">color:green;</xsl:param>
<xsl:param
name="attr-value-style">color:black;</xsl:param>
<xsl:param
name="attr-name-style">color:red</xsl:param>
<div>
<xsl:choose>
<xsl:when
test="self::comment()">
<xsl:attribute
name="style"><xsl:text>padding-left:</xsl:text><xsl:value-of
select="$indent"/></xsl:attribute>
<font
style="{$template-style}{$comment-style}">
<xsl:text><!--</xsl:text>
<xsl:value-of
select="$selnode"/>
<xsl:text>></xsl:text>
</font>
</xsl:when>
<xsl:when
test="self::processing-instruction()">
<xsl:attribute
name="style"><xsl:text>padding-left:</xsl:text><xsl:value-of
select="$indent"/></xsl:attribute>
<font
style="{$template-style}{$pi-style}">
<xsl:text><?</xsl:text>
<xsl:value-of
select="name()"/>
<xsl:text> </xsl:text>
<xsl:value-of
select="."/>
<xsl:text>?></xsl:text>
</font>
</xsl:when>
<xsl:when
test="self::text()">
<xsl:attribute
name="style"><xsl:text>display:inline;</xsl:text></xsl:attribute>
<font
style="{$template-style}{text-node-style}">
<xsl:call-template
name="html-replace-entities">
<xsl:with-param
name="text" select="$selnode"/>
</xsl:call-template>
</font>
</xsl:when>
<xsl:otherwise>
<xsl:attribute
name="style"><xsl:text>padding-left:</xsl:text><xsl:value-of
select="$indent"/></xsl:attribute>
<font
style="{$template-style}{$punctuation-style}">
<xsl:text><</xsl:text>
</font>
<font
style="{$template-style}{$node-name-style}">
<xsl:value-of
select="name($selnode)"/>
<xsl:for-each
select="$selnode/@*">
<xsl:text> </xsl:text>
<font
style="{$template-style}{$attr-name-style}">
<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:for-each>
<xsl:if
test="not(parent::*/parent::*)">
<xsl:for-each
select="namespace::*[position() > 1]">
<xsl:if
test="not(parent::*/parent::*)">
<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">
<xsl:with-param
name="from" select="'&'"/>
<xsl:with-param
name="to" select="'&amp;'"/>
<xsl:with-param
name="value" select="$text"/>
</xsl:call-template>
</xsl:with-param>
</xsl:call-template>
</xsl:with-param>
</xsl:call-template>
</xsl:with-param>
</xsl:call-template>
</xsl:with-param>
</xsl:call-template>
</xsl:variable>
<xsl:value-of
select="$tmp"/>
</xsl:template>
<xsl:template
name="replace-substring">
<xsl:param
name="value"/>
<xsl:param
name="from"/>
<xsl:param
name="to"/>
<xsl:choose>
<xsl:when
test="contains($value,$from)">
<xsl:value-of
select="substring-before($value,$from)"/>
<xsl:value-of
select="$to"/>
<xsl:call-template
name="replace-substring">
<xsl:with-param
name="value" select="substring-after($value,$from)"/>
<xsl:with-param
name="from" select="$from"/>
<xsl:with-param
name="to" select="$to"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of
select="$value"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
XQuery basically consist of two languages: the first is XQuery, a human-readable version, which is actually not XML, and the second is called XQueryX, the XML version of XQuery, which is intended to be used by (automating) applications rather than by human beings. In this tutorial however, we'll only look at the human-readable version, namely XQuery.
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 |
This group of expressions consist of literals, variables, parenthesized expressions, function calls, and comments. Each following expression type makes use of these 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 |
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 Expressions |
1.
document("xqt") 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. 2. <root> {
document("xqt")//title } </root> The output shown is: <?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> The output shown is: <?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:

Fig. 4: Screenshot of a working example with its output
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 |
XQuery works with sequences. Sequences are ordered collections of zero or more items. An item can be a value or a node. Sequences can be formed using either a Parenthesized Expression, an Expression Sequence, or a Range Expression. Additionally, sequences can be combined to form new sequences. |
|
Expression: |
Example(s): |
|
Sequence Expressions |
1. <seq> { (1,6,3)
} </seq> The output of this xquery is: <?xml
version="1.0"?> <seq>163</seq> |
|
Arithmetic Expressions |
XQuery has arithmetic expressions for addition, subtraction, multiplication, division, and modulus. For each expression, you can use the Unary Expression. |
|
Expression: |
Example(s): |
|
Arithmetic Expressions |
1. <sum> { 1 + 2 }
</sum> Output shown: <?xml
version="1.0"?> <sum>3</sum> |
|
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 Expressions |
1. <compare> { IF 3 > 2 THEN <yes/> ELSE <no/> } </compare> This xquery contains a conditional expression (see below for another example), and checks if the first operand of the test expression is greater than the second. This is the output: <?xml
version="1.0"?> <compare> <yes/> </compare> |
|
Logical Expressions |
This group contains the 'AND' and the 'OR' expression. |
|
Expression: |
Example(s): |
|
Logical Expressions |
1. <logical> { IF (3 > 2) AND (2 != 4) THEN <yes/> ELSE <no/> } </logical> The output produced by this xquery is: <?xml
version="1.0"?> <logical> <yes/> </logical> |
|
Constructors |
Constructors are a very powerful feature of XQuery. They allow you to add XML to your query for inclusion in the output tree. A special and much used type is the Enclosed Expression, used to enclose an expression to form a separate block. It also has constructors for creating CDATA sections and XML Processing Instructions. |
|
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 |
FLWR Expressions are pronounced as "flower expressions". This is one of the most powerful expression types of XQuery. It allows for writing xqueries in a SQL-like style, and can be fully nested. It also allows for processing xqueries very efficiently. FLWR expressions allow for the use of other kinds of expressions, like constructors, conditional, and logical expressions, and more. |
|
Expression: |
Example(s): |
|
FLWR Expressions |
1. <root> { FOR $a IN document("xqt")//tutorials RETURN $a/tutorial/title } </root> This xquery returns the following: <?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. A common way to nest FLWR Expressions is to include a new FLWR expression after the RETURN keyword; an example that builds on the previous example is as follows: 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> Although we do not have a second document (navigator) available (only "xqt" is present in the navigator collection), this xquery shows how we could produce a UNION of two or more different tables, using XQuery. The xquery produces the following output: <?xml
version="1.0"?> <root> <tutorial> <id>T000001</id> <id>T000002</id> <id>T000003</id> </tutorial> </root> |
|
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 Expressions |
1. <root> { 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 |
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 Expressions |
1. <root> { IF
document("xqt")//title/text()="xxx" THEN <true/> ELSE <false/> } </root> This expression will output the following: <?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> while this xquery wil return: <?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 |
Quantified Expressions are used to quantify items in a given node set. It uses a so-called quantifier in the form of the some and every keyword. The evaluation always gives a false or true, given an error-less expression. |
|
Expression: |
Example(s): |
|
Quantified Expressions |
1. SOME $a IN
document("xqt")//tutorials SATISFIES $a/tutorial/title This expression should evaluate to TRUE. Unfortunately, we can not test it since EVERY and SOME are not implemented yet. |
|
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. |
|
Expression: |
Example(s): |
|
Expressions on Datatypes |
Sa/title INSTANCE OF
ELEMENT OF TYPE xs:string This xquery should return TRUE, since the element title is an instance of type xs:string. This cannot be tested for the same reason as above. |
|
Validate Expressions |
The Validate Expressions are used to validate XQuery Expressions included within brackets. It also supports validating against an XML Schema. |
|
Expression: |
Example(s): |
|
Validate Expressions |
<root> { LET $a := validate{1,2,3,4,5} RETURN $a } </root> This expression validates the given expression in brackets. Once again, it is not implemented and can not be tested. |
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;
private
void Page_Load(object sender, System.EventArgs e)
{
// Put
user code to initialize the page here
}
#region
Web Form Designer generated code
override
protected void OnInit(EventArgs e)
{
//
//
CODEGEN: This call is required by _
the
ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}
///
<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
private
void btnExecXQuery_Click(object sender, System.EventArgs e)
{
if
(txtXMLsource.Text.Trim().Length != 0)
{
XQueryNavigatorCollection navCol = new XQueryNavigator _
Collection();
XmlDocument doc1 = new XmlDocument();
doc1.LoadXml(txtXMLsource.Text.Trim());
navCol.AddNavigator(doc1.CreateNavigator(), "xqt");
XQueryExpression expr = new XQueryExpression _
(txtXQueryExpr.Text.Trim());
XQueryNavigator nav;
nav =
expr.Execute(navCol);
XmlDocument doc2 = new XmlDocument();
doc2.LoadXml(nav.ToXml());
Xml1.Document = doc2;
Xml1.TransformSource = "xsl\\xqt.xsl";
}
}
}
}
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:
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;
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:
this.btnExecXQuery.Click += new
System.EventHandler(this.btnExecXQuery_Click);
The code for the button in question is the last code that was added to the page and is as follows:
private void btnExecXQuery_Click(object sender,
System.EventArgs e)
{
if
(txtXMLsource.Text.Trim().Length != 0)
{
XQueryNavigatorCollection navCol = new XQueryNavigatorCollection();
XmlDocument doc1 = new XmlDocument();
doc1.LoadXml(txtXMLsource.Text.Trim());
navCol.AddNavigator(doc1.CreateNavigator(), "xqt");
XQueryExpression expr = new XQueryExpression _
(txtXQueryExpr.Text.Trim());
XQueryNavigator nav;
nav =
expr.Execute(navCol);
XmlDocument doc2 = new XmlDocument();
doc2.LoadXml(nav.ToXml());
Xml1.Document = doc2;
Xml1.TransformSource = "xsl\\xqt.xsl";
}
}
The first line creates a new XQueryNavigatorCollection object:
XQueryNavigatorCollection navCol = new XQueryNavigatorCollection();
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:
XmlDocument doc1 = new XmlDocument();
doc1.LoadXml(txtXMLsource.Text.Trim());
navCol.AddNavigator(doc1.CreateNavigator(),
"xqt");
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.
XQueryExpression expr = new XQueryExpression(txtXQueryExpr.Text.Trim());
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:
XmlDocument doc2 = new XmlDocument();
doc2.LoadXml(nav.ToXml());
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";
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 *
*