Tutorial: Using XQuery in ASP.NET

 

Introduction_ 2

What is XQuery?_ 3

XQuery and ASP.NET_ 4

MS XQuery Demo_ 5

MS XQuery Demo namespace_ 5

Programming with the XQuery classes_ 6

XQuery Expression Tester_ 7

Creating the project 8

Adding the Reference 8

Building and Running the Application_ 8

The XML Source Document 9

The XSL Stylesheet 10

XQuery's Syntax and Examples_ 11

Primary Expressions_ 11

Path Expressions_ 12

Sequence Expressions_ 14

Arithmetic Expressions_ 15

Comparison Expressions_ 16

Logical Expressions_ 17

Constructors_ 18

FLWR Expressions_ 19

Sorting Expressions_ 20

Conditional Expressions_ 21

Quantified Expressions_ 22

Expressions on Datatypes_ 22

Validate Expressions_ 23

Code Explanation_ 23

Wrap-up_ 28

 

Introduction

 

This tutorial will introduce you to XQuery and help you how to use it in ASP.NET.  This article and the demo project are updated for use in VS.NET 2003 / .NET FW v1.1, with the MS XQuery Demo downloaded and installed.

 

The article will try to reflect the latest changes to the XQuery 1.0 specification, but due to the fact that Microsoft still has its implementation (MS XQuery Demo) based on the December 20, 2001 specification (see it here http://www.w3.org/TR/2001/WD-xquery-20011220/), I can only mention what has changed over time; if possible I’ll do that using references to specific sections of the W3C specification.

 

This article 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 Path 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 path expressions are extremely readable and easy to write.

 

During this exploration, you’ll be able to play with XQuery Path 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.).

 

Note: this project can be accessed live on my web-site – just point your browser to the following URL: [http://www.pietsieg.com/apps/xquery/XQueryTester/XQT.aspx]

 

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 soon.

 

There has been quite some updating on the drafts published since the start of the project. This year, the most important ones were:

1. 2 May 2003: Ten NEW working drafts published (two going to LAST CALL, one new, seven updates)

2. 22 August 2003: Five (updated) working drafts published (XPath 2.0, XQuery 1.0, XQuery 1.0 and XPath 2.0 Formal Semantics, XQuery Use Cases, XPath 2.0 Requirements)

 

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 shown, for the sake of simplicity):

 

 

Fig. 1: XQuery's relation to other W3C XML related specifications

 

In the above diagram, the specifications above the dashed line are W3C Recommendations. The specifications below the dashed line are currently what the W3C calls "Works in Progress"; as you can see, XQuery 1.0 is one of them.

 

Furthermore, we see that XPath 1.0 first was part of XSL 1.0 but later on grew out as a fully separate specification. The main reason for that was 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). Like XPath, XML Schema is also being re-used in other specifications.

 

XQuery 1.0 is tightly related to XPath 2.0, in that XQuery 1.0 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 1.0 is a transforming language and is single document based, XQuery 1.0 is more a querying language, is multiple documents based, and is more suitable for big XML source documents. In the end, it is expected that both will co-exist, and each one will cover different areas of possible applications, but also will share some overlap in certain areas, due to their similarities.

 

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.

 

XQuery and ASP.NET

 

As you may know, ASP.NET basically has the System.Xml namespace which extensively supports 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 from for example a database. You could also query a XML database. The important thing to remember here is that the XML source needs to be well-formed. Validating the XML 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 you write 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, if you didn’t already, go ahead, and download and install this first in your .NET Web server; you can get it at http://xqueryservices.com/Setup/xquery.msi. Note that if you only have installed the .NET FW v1.1 (which would be the case you installed VS.NET 2003 on a clean machine), the following message will appear:

 

 

Fig.2 : .NET FW RTM (Version 1.0) is required

 

Yes, you guessed it… it says that you must install the .NET FW v1.0 RTM first, to be able to install and use MS Xquery Demo. But there is an easier way to get things running: later on we’ll see that just copying the dll from the download ‘bin’ directory into your project ‘bin’ directory will suffice; adding the assembly to your references section will do the job.

 

But, if you would like to install the FW v1.0 RTM anyway because you would like to use the assembly in other projects also and have access to the accompanying documentation, then you can get it here: http://download.microsoft.com/download/a/2/4/a2457bb3-a43f-446f-ad8b-47cdcc72dc41/setup.exe (note that it’s a 100+ MB package, a hefty download for a 56kbps modem).

 

Once installed, the MS XQuery Demo managed class set lets you run your xqueries over your own XML source documents, be it one single document, or multiple ones.

 

MS XQuery Demo namespace

 

The MS XQuery managed classes reside in the namespace Microsoft.Xml.XQuery. They are designed for use together 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.

 

It is the object returned when an xquery is run over one or more navigators in the navigator collection object.

 

The class is also used for the objects within the navigator collection. All navigators possess the IXQueryNavigable Interface, which makes navigation possible and optimizes it.

XQueryDocument

This class provides an XML object to run xqueries over.

 

It has a method to create a new navigator, over which an xquery can be run.

XQueryNavigatorCollection

A collection of XQueryNavigator objects (navigators) to run xqueries over.

 

It is possible to run xqueries over one or more of each of these navigators.

XQueryExpression

This class provides an object which encapsulates the XQuery Expression – it is parsed, checked for any syntax error, and finally compiled.

 

Any errors are reported during each phase. An XQueryException is generated when the xquery is syntactically incorrect, if it generates a compiler error, or if it exceeds a certain string length.

 

After each phase has completely processes successful, it is ready to be run over the navigator collection – that is, the XQueryNavigatorCollection object.

XQueryException

This class provides for any exception thrown by the XQuery classes.

 

Programming with the XQuery classes

 

From the programming point of view, the classes needed to run an xquery are basically XQueryNavigator, XQueryNavigatorCollection, and XQueryExpression. How they interrelate can best be shown as follows:

 

 

Fig. 3: 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 (i.e., an XML file or a database table converted to XML). From now on, 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.

 

To be able to run xqueries, in the following 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.

 

XQuery Expression Tester

 

In this section, we'll create a simple ASP.NET Web Application 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 input will be captured and fed into a XmlDocument. Note that the XmlDocument from the System.Xml namespace is used here, instead of XQuerydocument.

 

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

 

Creating the project is simple. Start VS.NET 2003 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 but instead you use Windows Explorer, you also need to copy the ‘XQT.aspx.cs’ file).

 

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. Lastly, add another subdirectory called ‘xml’ and add the file ‘tut.xml’. Finally add the ‘Microsoft.Xml.XQuery.dll’ found in the download ‘bin’ directory, to your newly created directory ‘bin’.

 

Adding the Reference

 

Then, add a Reference to the project by choosing the menu "Project | Add Reference". In the .NET tab, use the Browse button, select the file named "Microsoft.Xml.XQuery.dll" which now resides in your bin directory, and click the button "Select". Finally, click OK. The reference should appear in the Solution Explorer, under the References directory. You can press [Ctrl+Alt+L] if you do not see the Solution Explorer.

 

Building and Running the Application

 

Before compiling, you'll need to choose a Start Up file before compiling and running your application. Choose "Set as Start Page" on "XQT.aspx" by right-clicking the project file in the Solution Explorer windowpane, and then finally press F5. After compiling the project, and activating the debugging environment, the following screen should turn up:

 

 

Fig. 4: 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 still 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 directory, then activate (Create) the web application using the Internet Services Manager (ISM), and run the application. Most of the time, it is sufficient to delete the .sln file, as this is the projects solution file, which contains the application path among other configuration items. In addition, the MS XQuery reference may need to be added again if the path is incorrect. VS.NET will indicate this to you also if this is the case.

 

OK, now you should be able to enter an 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 can write xqueries. After having run some xqueries using some of the most important XQuery Expression types, you'll quickly get the hang of constructing your own xqueries.

 

After this section is completed we'll be looking more in detail at how the code behind the web form works.

 

The XML Source Document

 

The XML source file we'll use throughout this section of the tutorial is named ‘tut.xml’. Press the button “Load XML Document ‘xqt’, and it’ll show up, as shown below:

 

 

Fig. 5: XQueryTester's look when the button ‘Load XML Document “xqt”’ is pressed

 

The XSL Stylesheet

 

Note that the XSL Stylesheet used here to present the resulting XML was originally written by Jason Patterson at the 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 the XQueryTester project is an updated version he personally sent me, and is not modified by me in any way. The stylesheet can be viewed by double-clicking on the file ‘xqt.xsl’ located in the projects subdirectory ‘xsl’. IE will show up and show it gracefully, using one of its built-in stylesheets:

 

 

Fig. 6 : IE showcases the stylesheet ‘xqt.xsl’

XQuery's Syntax and Examples

 

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.

 

XQuery consists of a set of powerful expressions. What kind of expressions does XQuery offer? There are Primary Expressions, Path Expressions, Sequence Expressions, Arithmetic Expressions, Comparison Expressions, Logical Expressions, Constructors, FLWR Expressions, Sorting Expressions, Conditional Expressions, and Quantified Expressions, and some more.

 

The following sections contain worksheets that will let you enter some example xqueries constructed using expression types, and run them over the XML source provided earlier in this tutorial. I recommend you get the XQueryTester up and running before continuing…

 

Primary Expressions

 

Primary Expressions

This group of expressions consists of literals, variables, parenthesized expressions, function calls, and comments.

 

Each following expression type makes use of these primary expressions.

 

I guess that a short explanation of each of the contained expressions is in place here. First, a literal consists of two types: numerical literals and string literals.

 

Numerical literals can contain integers, decimals, and doubles. They respectively evaluate to the data types xs:integer, xs:decimal, and xs:double. All three types contain series of digits in conjunction with representation methods for each data type.

 

String literals are a series of concatenated chars, enclosed by either single or double quotes. Its type evaluates to xs:string. A literal of zero characters is called an empty string.

 

In XQuery, variable expressions evaluate to the value of their QName, which is dependent of the evaluation context. XQuery allows static and dynamic variables to be used. Variables must be declared before they are used. More information on the term QName may be found at: http://www.w3.org/TR/REC-xml-names/#NT-QName

 

Parenthesized expressions are simply expressions contained in double quotes.

 

Function calls contain a QName (i.e., a variable which evaluates to a function calls’ name) and a parenthesized list of one or more expressions. Currently, unfortunately the MS XQuery Demo does not yet support any function call other than document().

 

Finally, comments are simply text strings enclosed in xqueries and are ignored by the XQuery processor.

 

No explicit examples are included here since these expression types are in fact the basic building blocks for use in all other XQuery Expression types that follow. So hold on, and you’ll soon see some basic xqueries appearing, that consist of combinations of the primary expressions mentioned above.

 

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.

 

If you query a document, you should always use the document() function, which takes the documents name as its parameter.

 

Worksheet 1: Path Expression examples

 

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>

 

which in this case is basically the same as

 

<root>

{ document("xqt")/root/tutorials/tutorial/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. From this xquery, a screenshot is added after the next third example.

 

3. <root>

     { document("xqt")//title/text() }

   </root>

 

Here, the input xquery is neatly formatted, but that does not influence the output in any way – it is just for readability and easy writing.

 

The output shown is:

 

<?xml version="1.0"?>

<root>Introduction to XQueryXQuery's

SyntaxXQuery: Advanced Tricks</root>

 

In this case, the values of the four found titles are concatenated into one string here (actually 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 next screenshot:

 

 

Fig. 7: 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

 

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 a Parenthesized Expression, an Expression Sequence, or a Range Expression. Additionally, sequences can be combined to form new sequences.

 

Worksheet 2: Sequence Expression examples

 

Expression:

Example(s):

Sequence Expressions

1. <seq> { (1,6,3) } </seq>

 

The output of this xquery is:

 

<?xml version="1.0"?>

<seq>163</seq>

 

2. <seq> { ( 6*3 , 10 div 5 , 3 mod 5 ) } </seq>

 

The output of this xquery is:

 

<?xml version="1.0"?>

<seq>1823</seq>

 

3. <seq> { ( "Hi" , " " , "there", "!" ) } </seq>

 

The output of this xquery is:

 

<?xml version="1.0"?>

<seq>Hi there!</seq>

 

 

Arithmetic Expressions

 

Arithmetic Expressions

XQuery has arithmetic expressions for addition, subtraction, multiplication, division, and modulus. For each expression, you can use the Unary Expression.

 

Worksheet 3: Arithmetic Expression examples

 

Expression:

Example(s):

Arithmetic Expressions

1. <sum> { 1 + 2 } </sum>

 

Output shown:

 

<?xml version="1.0"?>

<sum>3</sum>

 

2. <expr> { (55 * 100 + 55) * 2 + 1 } </expr>

 

Output shown:

 

<?xml version="1.0"?>

<expr>11111</expr>

 

3. <expr> { (50 div -5) * 2 } </expr>

 

Output shown:

 

<?xml version="1.0"?>

<expr>-20</expr>

 

 

Comparison Expressions

 

Comparison Expressions

This group of expressions is used to compare two values. XQuery supports four types of comparison expressions: value comparisons, general comparisons, node comparisons, and order comparisons.

 

Worksheet 4: Comparison Expression examples

 

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>

 

2. <str>

   {

     IF "right" = "left"

     THEN <yes/>

     ELSE <no/>

   }

   </str>

 

This xquery also contains a conditional expression, testing the equality of two strings. This is the output:

 

<?xml version="1.0"?>

<str>

  <no/>

</str>

 

3. <output>

   {

     IF 1234 >= 123

     THEN <y>yes, its greater</y>

     ELSE <n>no, its smaller</n>

   }

   </output>

 

This xquery compares two integer values, and outputs some XML on the decision "yes" or "no". This is the output:

 

<?xml version="1.0"?>

<output>

  <y>yes, its greater</y>

</output>

 

 

Logical Expressions

 

Logical Expressions

This group contains the 'AND' and the 'OR' expression.

 

Worksheet 5: Logical Expression examples

 

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>

 

2. <strcomp>

   {

     IF ("yes" = "no") OR ("007" = "7")

     THEN <yes/>

     ELSE <no/>

   }

   </strcomp>

 

The output produced by this xquery is:

 

<?xml version="1.0"?>

<strcomp>

  <no/>

</strcomp>

 

Of course, you could make the expression that evaluates as complex as you want – just remember that the output must always be false or true.

 

 

Constructors

 

Constructors

Constructors are a very powerful feature of XQuery. They allow you to add XML to your xquery 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.

 

Worksheet 6: Constructor examples

 

Expression:

Example(s):

Constructors

1. <root>

     <tutorial>

       <title>XQuery Explained</title>

     </tutorial>

   </root>

 

This produces the following output, which is fully self-explanatory – it simply copies the XML:

 

<?xml version="1.0"?>

<root>

  <tutorial>

    <title>XQuery Explained</title>

  </tutorial>

</root>

 

2. <root>

   <childnode></childnode>

   { IF document("xqt")//title[1] < "xxx" THEN

     <yes/> ELSE <no/> }

   </root>

 

This xquery produces the following output:

 

<?xml version="1.0"?>

<root>

  <childnode/>

  <yes/>

</root>

 

 

FLWR Expressions

 

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.

 

NOTE: currently, an ORDER BY clause has been added, so the name has changed to FLWOR, while the pronunciation stays the same. However, MS XQuery Demo is not yet based on the current specs, so this change will be incorporated by me in a future update when the demo is updated.

 

Worksheet 7: FLWR Expression examples

 

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

 

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.

 

Worksheet 8: Sorting Expression examples

 

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 by title, in ascending order, which is the default.

 

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: the output is the following text:

 

'SORTBY' is not implemented.

 

It runs however when you delete the bolded phrase "SORTBY (title)", and its output is shown here:

 

<?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 block.

 

Worksheet 9: Conditional Expression examples

 

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>

 

 

as you may have guessed already, this xquery will return:

 

<?xml version="1.0"?>

<root>

  <TRUE/>

</root>

 

As with the first example, the returned value is the Boolean 'TRUE' and not the string 'true'.

 

 

Quantified Expressions

 

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.

 

Worksheet 10: Quantified Expression examples

 

Expression:

Example(s):

Quantified Expressions

1. SOME $a IN document("xqt")//tutorials

   SATISFIES $a/tutorial/title

 

This expression should evaluate to TRUE. Unfortunately, we cannot test it since EVERY and SOME are not implemented yet in MS XQuery Demo; the catched XQueryException message is:

 

'some' is not implemented.

 

 

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.

 

Worksheet 11: Expression on Datatypes examples

 

Expression:

Example(s):

Expressions on Datatypes

1. 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; this time, the reported message is:

 

The query does not match the grammar.

 

 

Validate Expressions

 

Validate Expressions

Validate Expressions are used to validate XQuery Expressions, included within brackets. It also supports validating against an XML Schema.

 

Worksheet 12: Validate Expression examples

 

Expression:

Example(s):

Validate Expressions

1. <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 therefore cannot be tested – the message returned is:

 

Expected 'RETURN' where { encountered.

 

 

This concludes our tutorial. Although there are some interesting xqueries, it appears that the implementation does lack quite some functionality that would make MS XQuery Demo a really interesting option to consider using in our everyday programming practices.

 

But anyway, it is a demo, and will stay that way for some time more. I think that when the final status has been reached for some XQuery specifications by the W3C, current active implementers will update their products in a very short time.

 

Code Explanation

 

Well, now that you've seen some interesting simple xqueries and got a chance to play with them using ASP.NET, 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. The language used is C#. Then we'll examine 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;

using System.IO;

using System.Text;

 

namespace sitreperf

{

  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.Label lblError;

    protected System.Web.UI.WebControls.Button Button1;

    protected System.Web.UI.WebControls.Button btnExecXQuery;

 

    private void Page_Load(object sender, System.EventArgs e)

    {

      lblError.Visible = false;

    }

 

    #region Web Form Designer generated code

    override protected void OnInit(EventArgs e)

    {

      InitializeComponent();

      base.OnInit(e);

    }

           

    private void InitializeComponent()

    {   

      this.btnExecXQuery.Click += new

        System.EventHandler(this.btnExecXQuery_Click);

      this.Button1.Click += new

        System.EventHandler(this.Button1_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)

      {

        try

        {

          lblError.Visible = false;

          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";

        }

        catch (XQueryException xqe)

        {

          lblError.Visible = true;

          lblError.ForeColor = System.Drawing.Color.Red;

          lblError.Text = xqe.Message;

        }

        catch (XmlException xe)

        {

          lblError.Visible = true;

          lblError.ForeColor = System.Drawing.Color.Red;

          lblError.Text = xe.Message;

        }

      }

    }

 

    private void Button1_Click(object sender, System.EventArgs e)

    {

      string strPath = "xml/tut.xml";

      StreamReader objSR = new StreamReader(Server.MapPath(strPath),

        Encoding.Default);

      string strSRcontent = objSR.ReadToEnd();

      txtXMLsource.Text = strSRcontent;

    }

  }

}

 

First, we need to add the following namespaces to be able to use the System.Xml, the Microsoft.Xml.Xquery, the System.IO, and the System.Text namespaces:

 

using System.Xml;

using Microsoft.Xml.XQuery;

using System.IO;

using System.Text;

 

Then, when we add user controls to the page, and as we do so, 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.Label lblError;

protected System.Web.UI.WebControls.Button Button1;

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 handlers were automatically generated for us when double-clicking the buttons ‘Execute Xquery’ and ‘Button1’ to add the code behind it:

 

this.btnExecXQuery.Click += new

  System.EventHandler(this.btnExecXQuery_Click);

this.Button1.Click += new

  System.EventHandler(this.Button1_Click);

 

The code for the button ‘Execute Xquery’ is as follows:

 

private void btnExecXQuery_Click(object sender, System.EventArgs e)

{

  if (txtXMLsource.Text.Trim().Length != 0)

  {

    try

    {

      lblError.Visible = false;

      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";

    }

    catch (XQueryException xqe)

    {

      lblError.Visible = true;

      lblError.ForeColor = System.Drawing.Color.Red;

      lblError.Text = xqe.Message;

    }

    catch (XmlException xe)

    {

      lblError.Visible = true;

      lblError.ForeColor = System.Drawing.Color.Red;

      lblError.Text = xe.Message;

    }

  }

}

 

The second 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 using the try-catch construct (see later).

 

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";

 

The last line above applies an XSLT on the resulting XML from the xquery, before returning the final output to the user's browser.

 

All the above code is checked for errors, and we are especially interested in catching two exceptions, the XQueryException, and the XmlException. If either one of these two occurs, the exception is catched and an explaining error message is outputted to the error label which is situated at the same place as the XML Server Web Control

 

catch (XQueryException xqe)

{

  lblError.Visible = true;

  lblError.ForeColor = System.Drawing.Color.Red;

  lblError.Text = xqe.Message;

}

catch (XmlException xe)

{

  lblError.Visible = true;

  lblError.ForeColor = System.Drawing.Color.Red;

  lblError.Text = xe.Message;

}

 

This section has shown and explained you the code, which is required to create a singular navigator collection, and run some xqueries over it.

 

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 now should enable 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 (or files) you need to query, and then run nested FLWR xqueries over it, just like you would do using SQL.