0% found this document useful (0 votes)
93 views123 pages

Xquery: Roger L. Costello 16 June 2010

The document provides information about XQuery including: 1. XQuery is a query language for XML that is a superset of XPath 2.0 and allows users to select nodes, compare nodes, perform operations on nodes, and create nodes. 2. The structure of an XQuery document includes an optional prolog and a required body which can contain a single expression or sequence of expressions separated by commas. 3. XQuery can be used to query XML documents, embedded in other documents like HTML, and allows implicit or explicit specification of the input XML document.

Uploaded by

jain_gaurav001
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
93 views123 pages

Xquery: Roger L. Costello 16 June 2010

The document provides information about XQuery including: 1. XQuery is a query language for XML that is a superset of XPath 2.0 and allows users to select nodes, compare nodes, perform operations on nodes, and create nodes. 2. The structure of an XQuery document includes an optional prolog and a required body which can contain a single expression or sequence of expressions separated by commas. 3. XQuery can be used to query XML documents, embedded in other documents like HTML, and allows implicit or explicit specification of the input XML document.

Uploaded by

jain_gaurav001
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 123

1

XQuery
http://www.w3.org/TR/xquery/

Roger L. Costello 16 June 2010

Prerequisites
This tutorial assumes you know XPath 1.0 and XPath 2.0 If you don't know XPath then please read my XPath tutorials at: http://www.xfront.com/xpath/

XQuery Mailing List


There is a world-wide XQuery mailing list, [email protected] Here's the web page where you can subscribe:
http://www.x-query.com/mailman/listinfo/talk

Usage

XQuery Processor
FitnessCenter.xml

HTML, XML, text

FitnessCenter.xq
Note: The file extension may be .xq or .xquery

XQuery Processor: SAXON


SAXON is both an XSLT processor as well as an XQuery processor. I created a DOS batch file to enable you to invoke the SAXON XQuery processor. In the examples folders you will find: run-saxon.bat Here's how to use it:
run-saxon FitnessCenter.xml FitnessCenter.xq FitnessCenter.html

Execute XQueries in Oxygen XML


Open Oxygen. Drag and drop an XQuery file into Oxygen. Click on the wrench icon:

Click on this wrench icon

Execute XQuery in Oxygen XML (cont.)

1. Choose XQuery transformation

2. Click on New

Execute XQuery in Oxygen XML (cont.)

1. Select the XML file.

2. Click on OK

Execute XQuery in Oxygen XML (cont.)

Click on OK

10

1. Click on this

2. Results are shown here

11

XQuery = XPath 2.0 + more


XQuery XPath 2.0
XPath 1.0 XQuery is a superset of XPath 2.0, which is a superset of XPath 1.0

12

Query this XML


We will use this XML <?xml version="1.0"?> document throughout <FitnessCenter> <Member level="platinum"> the tutorial, so spend a <Name>Jeff</Name> minute or two <FavoriteColor>lightgrey</FavoriteColor> familiarizing yourself </Member> with it.

<Member level="gold"> <Name>David</Name> It is FitnessCenter.xml <FavoriteColor>lightblue</FavoriteColor> in the example01 </Member> folder. Please load it <Member level="platinum"> <Name>Roger</Name> into Oxygen XML. <FavoriteColor>lightyellow</FavoriteColor> </Member> </FitnessCenter>

FitnessCenter.xml

13

{ XQuery expression }
To indicate that an expression is an XQuery expression and is to be evaluated, wrap the expression within curly braces, e.g.,
<NAMES>{for $i in //Member return $i/Name/text()}</NAMES>

14

XPath can't create elements and attributes, XQuery can!


XPath allows you to select nodes, compare nodes, and perform operations on nodes. But it doesn't allow you to create nodes, e.g., you can't have an XPath expression that creates <Name>Linda</Name> With XQuery you can create nodes.

15

Select each member's name and wrap each name in a list item, <li>, element:

<ul>{for $i in //Member return <li>{$i/Name/text()}</li>}</ul>

16

Result
<ul> <li>Jeff</li> <li>David</li> <li>Roger</li> </ul>

The XQuery created <li> elements! And the XQuery filled the <li> elements with data from the XML document.

17

Note the curly braces within curly braces


<ul>{for $i in //Member return <li>{$i/Name/text()}</li>}</ul>

18

Rule for using curly braces


<ul>{for $i in //Member return <li>{$i/Name/text()}</li>}</ul>

Whenever you have an element whose contents is an XQuery expression that you want evaluated, you must wrap the expression within curly braces.

19

for $i in //Member return <li>{$i/Name/text()}</li> Output: <li>Jeff</li> <li>David</li> <li>Roger</li> for $i in //Member return <li>$i/Name/text()</li> Output: <li>$i/Name/text()</li> <li>$i/Name/text()</li> <li>$i/Name/text()</li> No curly brace, no evaluation!

for $i in //Member return $i/Name/text()


Output: JeffDavidRoger
see example02

20

Structure of an XQuery Document


Prolog (optional)

Body (required)

21

Structure of the XQuery Body


The XQuery body is a single expression, but that expression can consist of a sequence of one or more expressions that are separated by commas.
expression

22

XQuery embedded in HTML


<?xml version="1.0"?> <FitnessCenter> <Member level="platinum"> <Name>Jeff</Name> <FavoriteColor>lightgrey</FavoriteColor> </Member> <Member level="gold"> <Name>David</Name> <FavoriteColor>lightblue</FavoriteColor> </Member> <Member level="platinum"> <Name>Roger</Name> <FavoriteColor>lightyellow</FavoriteColor> </Member> </FitnessCenter> <html> <head> <title>Member Names</title> </head> <body> <h1>Member Names</h1> <ul> {for $i in //Member return <li>{$i/Name/text()}</li>} </ul> </body> </html>

FitnessCenter.xq
Evaluate the XQuery
<html> <head> <title>Member Names</title> </head> <body> <ul> <li>Jeff</li> <li>David</li> <li>Roger</li> </ul> </body> </html>

FitnessCenter.xml

see example01

23

Validate your XQuery


You can validate your XQuery before you execute it. Drag and drop the XQuery document into Oxygen XML. Then click on the red checkmark (in the toolbar). If your XQuery is not a valid expression you will get an error message.

24

Implicit vs Explicit Input


This XQuery queries an implicit XML document:
for $i in //Member return <li>{$i/Name/text()}</li>

This XQuery explicitly specifies the XML document to be queried:


for $i in doc('FitnessCenter.xml')//Member return <li>{$i/Name/text()}</li>

25

Explicit Input
<html> <head> <title>Member Names</title> </head> <body> <h1>Member Names</h1> <ul> {for $i in doc('FitnessCenter.xml')//Member return <li>{$i/Name/text()}</li>} </ul> </body> </html>

Evaluate the XQuery

<html> <head></head> <body> <ul> <li>Jeff</li> <li>David</li> <li>Roger</li> </ul> </body> </html>

FitnessCenter.xq

<?xml version="1.0"?> <FitnessCenter> <Member level="platinum"> <Name>Jeff</Name> <FavoriteColor>lightgrey</FavoriteColor> </Member> <Member level="gold"> <Name>David</Name> <FavoriteColor>lightblue</FavoriteColor> </Member> <Member level="platinum"> <Name>Roger</Name> <FavoriteColor>lightyellow</FavoriteColor> </Member> </FitnessCenter>

FitnessCenter.xml

26

Run SAXON with 2 Arguments


I created a DOS batch file to enable you to invoke SAXON with just the name of the XQuery file and the name of the output file. In the example01-a folder you will find: run-saxon-2-args.bat Here's how to use it:
run-saxon-2-args FitnessCenter.xq FitnessCenter.html

see example01-a

27

Getting the value of an element versus copying an element


XSLT <xsl:value-of select="$i/Name"/> XQuery $i/Name/text() or string($i/Name) or data($i/Name) $i/Name

<xsl:copy-of select="$i/Name"/> Lessons Learned:

1. In XQuery, if you want to get the value of an element either: use the text() function, or wrap the element name within the string() function, or wrap the element name within the data() function 2. In XQuery, if you want to get a copy of an element then give the element name.

for $i in //Member return $i/Name/text() Output: JeffDavidRoger

28

for $i in //Member return string($i/Name)


Output: Jeff David Roger

for $i in //Member return data($i/Name)


Output: Jeff David Roger for $i in //Member return $i/Name Output: <Name>Jeff</Name> <Name>David</Name> <Name>Roger</Name>

see example03

29

Sequence of Expressions
If you have a sequence of expressions that you want evaluated then you must:
separate each expression by a comma wrap the expressions in ( )

for $i in //Member return ("Name = ", $i/Name/text(), " FavoriteColor = ", $i/FavoriteColor/text())

( expr1,

expr2,

expr3,

expr4 )

30

If you forget to wrap the sequence in parentheses ...


for $i in //Member return "Name = ", $i/Name/text(), " FavoriteColor = ", $i/FavoriteColor/text()

Here's the error message that you get:


Error XQuery syntax error on line 23 of file:/C:/new-xml-course/xquery/examples/example04/FitnessCenter.xq in `...mber return "Name = ", $i/Name`: Variable $i has not been declared Failed to compile query: XQuery syntax error Query processing failed: net.sf.saxon.xpath.StaticError: XQuery syntax error

31 for $i in //Member return (" Name = ", $i/Name/text(), " FavoriteColor = ", $i/FavoriteColor/text())

Output:
Name = Jeff FavoriteColor = lightgrey Name = David FavoriteColor = lightblue Name = Roger FavoriteColor = lightyellow for $i in //Member return <Member>{("Name = ", $i/Name/text(), " FavoriteColor = ", $i/FavoriteColor/text())}</Member>

Output:
<Member>Name = Jeff FavoriteColor = lightgrey</Member> <Member>Name = David FavoriteColor = lightblue</Member> <Member>Name = Roger FavoriteColor = lightyellow</Member> for $i in //Member return <Member> <Name>{("Name = ", $i/Name/text())}</Name> <FavoriteColor>{("FavoriteColor = ", $i/FavoriteColor/text())}</FavoriteColor> </Member>

Output:
<Member> <Name>Name = Jeff</Name> <FavoriteColor>FavoriteColor = lightgrey</FavoriteColor> </Member> <Member> <Name>Name = David</Name> <FavoriteColor>FavoriteColor = lightblue</FavoriteColor> </Member> <Member> <Name>Name = Roger</Name> <FavoriteColor>FavoriteColor = lightyellow</FavoriteColor> /Member> see example04

32

XQuery embedded in XML


<?xml version="1.0"?> <FitnessCenter> <Member level="platinum"> <Name>Jeff</Name> <FavoriteColor>lightgrey</FavoriteColor> </Member> <Member level="gold"> <Name>David</Name> <FavoriteColor>lightblue</FavoriteColor> </Member> <Member level="platinum"> <Name>Roger</Name> <FavoriteColor>lightyellow</FavoriteColor> </Member> </FitnessCenter> <?xml version="1.0"?> <test> <result> { for $i in //Member return <Member> <Name>{("Name = ", $i/Name/text())}</Name> <FavoriteColor> {("FavoriteColor = ", $i/FavoriteColor/text())} </FavoriteColor> </Member> } </result> </test>

FitnessCenter.xq
Evaluate the XQuery
<?xml version="1.0"?> <test> <result> <Member> <Name>Name = Jeff</Name> <FavoriteColor>FavoriteColor = lightgrey</FavoriteColor> </Member> <Member> <Name>Name = David</Name> <FavoriteColor>FavoriteColor = lightblue</FavoriteColor> </Member> <Member> <Name>Name = Roger</Name> <FavoriteColor> FavoriteColor = lightyellow<</FavoriteColor>

FitnessCenter.xml

33

Default Namespace
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> </head>

<body>
<h1>Fitness Center</h1> <div id="fitness"> { for $i in //Member return } </div> </body>

</html>

Trying to iterate through <Member> elements in the default (XHTML) namespace!

34

Rule: put XML in a namespace


<?xml version="1.0"?> <FitnessCenter xmlns="http://www.gym.com"> <Member level="platinum"> <Name>Jeff</Name> <FavoriteColor>lightgrey</FavoriteColor> </Member> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" </FitnessCenter> xmlns:gym="http://www.gym.com"> <head> </head> <body> <h1>Fitness Center</h1> <div id="fitness">

{
for $i in //gym:Member return

35

DOCTYPE Declaration
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> ... </html>

You will get this error about the DOCTYPE:


Error on line 1 column 0 of planets.xq: XPST0003: XQuery syntax error in #<!D#: Expected '--' or '[CDATA[' after '<!' Static error(s) in query

36

Specifying HTML output with a DOCTYPE


declare namespace saxon = "http://saxon.sf.net/"; declare option saxon:output "indent=no"; declare option saxon:output "method=html"; declare option saxon:output "doctype-public=-//W3C//DTD XHTML 1.0 Strict//EN"; declare option saxon:output "doctype-system=http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"; <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> </html>

Evaluate the XQuery


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> ... </html>

37

Specifying XML output


declare namespace saxon = "http://saxon.sf.net/"; declare option saxon:output "indent=no"; declare option saxon:output "method=xml";

Actually, the default output is XML. So, you can omit these three lines.

38

Output types
declare namespace saxon = "http://saxon.sf.net/"; declare option saxon:output "indent=no"; declare option saxon:output "method=____";

html, xhtml, xml, or text

39

Creating Attributes
Recall $i/Name returns a copy of the <Name> element: for $i in //Member return $i/Name Output: <Name>Jeff</Name> <Name>David</Name> <Name>Roger</Name>

When used in assigning an attribute a value, $i/Name returns the value of the <Name> element: for $i in //Member return <Member name="{$i/Name}" /> Output: <Member name="Jeff" /> <Member name="David" /> <Member name="Roger" />

40

Equivalent
for $i in //Member return <Member name="{$i/Name}" />

Output:
<Member name="Jeff" /> <Member name="David" /> <Member name="Roger" /> for $i in //Member return <Member name="{string($i/Name)}" />

Output:
<Member name="Jeff" /> <Member name="David" /> <Member name="Roger" />

for $i in //Member return <Member name="{data($i/Name)}" />

Output:
<Member name="Jeff" /> <Member name="David" /> <Member name="Roger" /> see example05 Do Lab1

41

Creating Attributes (cont.)


$i/@id returns an attribute-value pair that then gets added to the enclosing element.

for $i in //Member return <Member>{$i/@id}</Member>

Output:
<Member id="1" /> <Member id="2" /> <Member id="3" />

42

Create 2 Attributes
for $i in //Member return <Member>{($i/@id, $i/@level)}</Member>

Output:
<Member id="1" level="platinum" /> <Member id="2" level="gold" /> <Member id="3" level="platinum" />

Remember to wrap the sequence in parentheses and separate the expressions by commas.
see example05

43

Creating 3 Attributes
{ for $i in //Member return <Member name="{$i/Name}">{($i/@id, $i/@level)}</Member> }

Output:
<Member name="Jeff" id="1" level="platinum" /> <Member name="David" id="2" level="gold" /> <Member name="Roger" id="3" level="platinum" />

see example05

44

Create Element Value from Attribute


The last few slides showed how to input an attribute and use it to create an attribute. Here's how to input an attribute and use it as the value of an element:
for $i in //Member return <Member>{data($i/@id)}</Member>

Output:
<Member>1</Member> <Member>2</Member> <Member>3</Member>

45

Equivalent
for $i in //Member return <Member>{data($i/@id)}</Member>

Output:
<Member>1</Member> <Member>2</Member> <Member>3</Member>
for $i in //Member return <Member>{string($i/@id)}</Member>

Output:
<Member>1</Member> <Member>2</Member> <Member>3</Member>
see example05

46

Create Element and Attribute


for $i in //Member return <Member>{($i/@id, data($i/@level)))}</Member>

Output:
<Member id="1">platinum</Member> <Member id="2">gold</Member> <Member id="3">platinum</Member>

see example05

FitnessCenter.xml

<?xml version="1.0"?> <FitnessCenter> <Member level="platinum"> <Name>Jeff</Name> <FavoriteColor>lightgrey</FavoriteColor> </Member> <Member level="gold"> <Name>David</Name> <FavoriteColor>lightblue</FavoriteColor> </Member> <Member level="platinum"> <Name>Roger</Name> <FavoriteColor>lightyellow</FavoriteColor> </Member> </FitnessCenter>

47

FitnessCenter.xq

<MemberInfo> <Names> { for $i in //Member return $i/Name } </Names> <FavoriteColors> { for $i in //Member return $i/FavoriteColor } </FavoriteColors> </MemberInfo>

MemberInfo.xml

<?xml version="1.0"?> <MemberInfo> <Names> <Name>Jeff</Name> <Name>David</Name> <Name>Roger</Name> </Names> <FavoriteColors> <FavoriteColor>lightgrey</FavoriteColor> <FavoriteColor>lightblue</FavoriteColor> <FavoriteColor>lightyellow</FavoriteColor> </FavoriteColors> </MemberInfo>

Do Lab2 see example07

FitnessCenter.xml

<?xml version="1.0"?> <FitnessCenter> <Member level="platinum"> <Name>Jeff</Name> <FavoriteColor>lightgrey</FavoriteColor> </Member> <Member level="gold"> <Name>David</Name> <FavoriteColor>lightblue</FavoriteColor> </Member> <Member level="platinum"> <Name>Roger</Name> <FavoriteColor>lightyellow</FavoriteColor> </Member> </FitnessCenter>

48

FitnessCenter.xq ???

Members.xml

<?xml version="1.0"?> <Members> <platinum> <Name>Jeff</Name> <Name>Roger</Name> </platinum> <gold> <Name>David</Name> </gold> </Members>

49

Non-Extensible Solution
<Members> <platinum> { for $i in //Member[@level eq "platinum"] return $i/Name } </platinum> <gold> { for $i in //Member[@level eq "gold"] return $i/Name } </gold> </Members>

This XQuery document hardcodes the elements <platinum> and <gold>. Suppose that other levels were added (e.g., silver)? This solution would miss them. So, how do we make the solution more robust? see example08

50

Here's what we desire


<Members> { for $i in distinct-values(//Member/@level) return create an element with name string($i) and value: { for $j in //Member[@level eq $i] return $j/Name } } </Members>

51

element {name} {value}


Here are examples of using the element keyword to dynamically create an element:
element {"FavoriteColor"} {"blue"} Output: <FavoriteColor>blue</FavoriteColor>

element {"Numbers"} {1 to 10}


Output: <Numbers>1 2 3 4 5 6 7 8 9 10</Numbers>
see example09

52

Another Example
element {name(/*/*[1])} {/*/*[1]/*} Output: <Member> <Name>Jeff</Name> <FavoriteColor>lightgrey</FavoriteColor> </Member>

"The name of the element is the name of the first child of the root element. The value of the element is the content of the first child of the root element."
see example09

53

Solving the problem using a computed element constructor


<Members> { for $i in distinct-values(//Member/@level) return element {string($i)} { for $j in //Member[@level eq $i] return $j/Name } } </Members>

The element name is computed using the value of $i. This is called a computed element constructor.
see example10

54

Sequence values are always separated by commas


<aircraft> { element altitude {12000}, element speed {160} } </aircraft> Notice the comma. It separates the two element sequence values.

Output: <aircraft> <altitude>12000</altitude> <speed>160</speed> </aircraft>


see example11

55

If you forget the comma ...


<aircraft> { element altitude {12000} element speed {160} } </aircraft> Notice there is no comma.

Output:
Error XQuery syntax error on line 4 of file:/C:/new-xml-course/xquery/examples/example11/aircraft.xq in `...0} element speed {160`: expected "}", found "null" Failed to compile query: XQuery syntax error Query processing failed: net.sf.saxon.xpath.StaticError: XQuery syntax error

56

attribute {name} {value}


and

text {value}
Here are examples of using the attribute keyword and the text keyword to create an attribute and text node, respectively:
<aircraft> { element {"altitude"} { attribute {"units"} {"feet"}, text {12000} }, element {"speed"} { attribute {"units"} {"knots"}, text {160} } } </aircraft>

Output: <aircraft> <altitude units="feet">12000</altitude> <speed units="knots">160</speed> </aircraft>

see example12

57

Use commas!
<aircraft> { element {"altitude"} { attribute {"units"} {"feet"}, text {12000} }, element {"speed"} { attribute {"units"} {"knots"}, text {160} } } </aircraft>

separate the units attribute from the text node. separate the altitude element from the speed element. separate the units attribute from the text node.

REMINDER: SEQUENCE VALUES ARE ALWAYS SEPARATED BY COMMAS!

58

FitnessCenter.xml

<?xml version="1.0"?> <FitnessCenter> <Member level="platinum"> <Name>Jeff</Name> <MembershipFee>500</MembershipFee> </Member> <Member level="gold"> <Name>David</Name> <MembershipFee>400</MembershipFee> </Member> <Member level="platinum"> <Name>Roger</Name> <MembershipFee>500</MembershipFee> </Member> </FitnessCenter>

FitnessCenter.xq ???

MembershipLevelCosts.xml

<?xml version="1.0"?> <MembershipLevelCosts> <level platinum="500"/> <level gold="400"/> </MembershipLevelCosts>

59

FitnessCenter.xq
<MembershipLevelCosts> { for $i in distinct-values(//Member/@level) return element {"level"} { attribute {$i} {//Member[@level eq $i][1]/MembershipFee} } } </MembershipLevelCosts>

Output:
<MembershipLevelCosts> <level platinum="500"/> <level gold="400"/> </MembershipLevelCosts>
see example13

60

Computed Attribute Constructor


<MembershipLevelCosts> { for $i in distinct-values(//Member/@level) return element {"level"} { attribute {$i} {//Member[@level eq $i][1]/MembershipFee} } } </MembershipLevelCosts>

The attribute name is computed using the value of $i. This is called a computed attribute constructor.
Do Lab3

61

Computed Document Constructor


This is used to create a document node: document {value}

62

document {value}
document { element {"aircraft"} { element {"altitude"} { attribute {"units"} {"feet"}, text {12000} }, element {"speed"} { attribute {"units"} {"knots"}, text {160} } } } Output: <aircraft> <altitude units="feet">12000</altitude> <speed units="knots">160</speed> </aircraft>

see example14

63

Summary of Computed Constructors


document {value} A document node is created. The name of the element is computed. The name of the attribute is computed. A text node is created.

element {name} {value}


attribute {name} {value}

text {value}

64

Terminology
This is called a direct element constructor: <altitude>12000</altitude>

This is called a computed element constructor:


element {"altitude"} { text {12000} }

65

Not XML
element {"altitude"} { attribute {"units"} {"feet"}, text {12000} }, element {"speed"} { attribute {"units"} {"knots"}, text {160} } Output: <altitude units="feet">12000</altitude> <speed units="knots">160</speed>

This is a perfectly fine output document. It's not an XML document. It has no root element.

This is a perfectly fine XQuery document. It's not an XML document. It has no markup. It has no root element.
see example15-a

66

No XML Declaration
Do not put an XML declaration at the top of your XQuery document.
<?xml version="1.0"?> element {"altitude"} { attribute {"units"} {"feet"}, text {12000} }, element {"speed"} { attribute {"units"} {"knots"}, text {160} }

67

An XQuery Document is NOT an XML Document


Reserved XML characters such as "<" do not need to be escaped (in fact, they must not be escaped). There is overlap between XML and XQuery:
Every start tag must have a matching end tag.

XQuery

XML

68

Do not escape "<" or ">"


<Results> {if (1 < 2) then "1 < 2 is TRUE" else "1 < 2 is FALSE"}, {if (1 > 2) then "1 > 2 is TRUE" else "1 > 2 is FALSE"} </Results>

Output: <Results> 1 < 2 is TRUE, 1 > 2 is FALSE </Results >

see example15

69

Whitespace
By default whitespace that occurs around an evaluated expression is stripped.
Output:
<WhitespaceTests> <Test> hi </Test> <Test> {"hi"} </Test> <Test> &#x20; {"hi"} </Test> <Test>{1 to 10}</Test> <Test> {1 to 10} </Test> <Test> {"hi"},{"there"} </Test> <Test>{" "}</Test> <Test>{1,2,3}</Test> <Test> {1,2,3} </Test> <Test>{1}{2}{3}</Test> <Test> {1}{2}{3} </Test> </WhitespaceTests> <WhitespaceTests> <Test> hi </Test> <Test>hi</Test> <Test> hi</Test> <Test>1 2 3 4 5 6 7 8 9 10</Test> <Test>1 2 3 4 5 6 7 8 9 10</Test> <Test>hi,there</Test> <Test> </Test> <Test>1 2 3</Test> <Test>1 2 3</Test> <Test>123</Test> <Test>123</Test> </WhitespaceTests>

see example16

70

XQuery can sort values


XPath provides no way to sort values. With XQuery you can sort values.

71

for $i in expr1 order by expr2 return expr3


<html> <body> <ul> { for $i in //Member order by $i/Name/text() ascending return <li>{$i/Name/text()}</li> } </ul> </body> </html>

Output: David Jeff Roger

order by expr is used to specify how you want the data sorted. In this example I specified that I want the Members sorted using the Name field in ascending order.

see example17

72

Sort the Numbers <= 20


<?xml version="1.0"?> <Numbers> <Number>0</Number> <Number>8</Number> <Number>23</Number> <Number>17</Number> <Number>5</Number> <Number>19</Number> <Number>44</Number> <Number>13</Number> <Number>78</Number> <Number>21</Number> <Number>2</Number> <Number>1</Number> <Number>15</Number> <Number>67</Number> <Number>99</Number> <Number>14</Number> <Number>8</Number> <Number>33</Number> <Number>50</Number> </Numbers> <html> <body> <ul> { for $i in //Number[number(text()) <= 20] order by number($i) ascending return <li>{$i/text()}</li> } </ul> </body> </html>

Numbers.xq Output:
0 1 2 5 8 8 13 14 15 17 19 see example18

Numbers.xml

73

for $i in expr1 where expr2 order by expr3 return expr4


<?xml version="1.0"?> <Numbers> <Number>0</Number> <Number>8</Number> <Number>23</Number> <Number>17</Number> <Number>5</Number> <Number>19</Number> <Number>44</Number> <Number>13</Number> <Number>78</Number> <Number>21</Number> <Number>2</Number> <Number>1</Number> <Number>15</Number> <Number>67</Number> <Number>99</Number> <Number>14</Number> <Number>8</Number> <Number>33</Number> <Number>50</Number> </Numbers>

Here's an alternative (equivalent) solution using "where expr":


<html> <body> <ul> { for $i in //Number where number($i) <= 20 order by number($i) ascending return <li>{$i/text()}</li> } </ul> </body> </html>

Numbers_v2.xq Output:
0 1 2 5 8 8 13 14 15 17 19 see example18

Numbers.xml

74

Equivalent
for $i in //Number[number(text()) <= 20] ...

for $i in //Number where number($i) <= 20 ...

75
<?xml version="1.0"?> <MemberNames> <Member id="1"> <Name>Jeff</Name> </Member> <Member id="2"> <Name>David</Name> </Member> <Member id="3"> <Name>Roger</Name> </Member> <Member id="4"> <Name>Stacey</Name> </Member> <Member id="5"> <Name>Linda</Name> </Member> <Member id="6"> <Name>John</Name> </Member> <Member id="7"> <Name>Diane</Name> </Member> <Member id="8"> <Name>Andy</Name> </Member> <Member id="9"> <Name>Josh</Name> </Member> <Member id="10"> <Name>Donna</Name> </Member> </MemberNames>

Join each Member's Name with their Age

This data is sorted by id value

This data is sorted by Name

David Jeff Linda Roger Stacey

39 35 40 32 25

<?xml version="1.0"?> <MemberAges> <Member id="8"> <Age>19</Age> </Member> <Member id="7"> <Age>22</Age> </Member> <Member id="4"> <Age>25</Age> </Member> <Member id="10"> <Age>29</Age> </Member> <Member id="3"> <Age>32</Age> </Member> <Member id="1"> <Age>35</Age> </Member> <Member id="2"> <Age>39</Age> </Member> <Member id="5"> <Age>40</Age> </Member> <Member id="6"> <Age>44</Age> </Member> <Member id="9"> <Age>50</Age> </Member> </MemberAges>

This data is sorted by Age

Just interested in the first 5 Members (i.e., @id <= 5)

76
<?xml version="1.0"?> <MemberNames> <Member id="1"> <Name>Jeff</Name> </Member> <Member id="2"> <Name>David</Name> </Member> </MemberNames> <?xml version="1.0"?> <MemberAges> ... <Member id="1"> <Age>35</Age> </Member> <Member id="2"> <Age>39</Age> </Member> ... </MemberAges>

$i

$j

MemberNames.xml

MemberAges.xml

<table border="1"> { for $i in //Member, $j in doc("MemberAges.xml")//Member[@id eq $i/@id]/Age where number($i/@id) <= 5 order by $i/Name/text() ascending return <tr> <td>{$i/Name/text()}</td> <td>{$j/text()}</td> </tr> } </table>

MemberInfo.xq
see example19

77

for $i in expr1 let $j := expr2 where expr3 order by expr4 return expr5
$i
<?xml version="1.0"?> <MemberNames> <Member id="1"> <Name>Jeff</Name> </Member> <Member id="2"> <Name>David</Name> </Member> </MemberNames>

$j

<?xml version="1.0"?> <MemberAges> ... <Member id="1"> <Age>35</Age> </Member> <Member id="2"> <Age>39</Age> </Member> ... </MemberAges>

<table border="1"> { for $i in //Member let $j := doc("MemberAges.xml")//Member[@id eq $i/@id]/Age where number($i/@id) <= 5 order by $i/Name/text() ascending return <tr> <td>{$i/Name/text()}</td> <td>{$j/text()}</td> </tr> } </table>

This is an alternate (equivalent) solution

MemberInfo_v2.xq
see example19

78

Equivalent
for $i in //Member, $j in doc("MemberAges.xml")//Member[@id eq $i/@id]/Age

for $i in //Member let $j := doc("MemberAges.xml")//Member[@id eq $i/@id]/Age

79

FLWOR
Pronounced: Flower for-let-where-order-return
for $i in //Member let $j := doc("MemberAges.xml")//Member[@id eq $i/@id]/Age where number($i/@id) <= 5 order by $i/Name/text() ascending return ...

Here's how FLWOR is defined: (for expr | let expr)+ (where expr)? (order by expr)? return expr

80

let $j := expr
The let clause is not a looping mechanism. It is only a variable assignment mechanism.
<table border="1"> <tr><th>$i</th><th>$j</th><th>$k</th></tr> { for $i in (1 to 3) let $j := ("red", "white", "blue") for $k in (4 to 6) return <tr> <td>{$i}</td> <td>{$j}</td> <td>{$k}</td> </tr> } </table>

Output:
$i 1 1 1 2 2 2 3 3 3 red red red red red red red red red $j white blue white blue white blue white blue white blue white blue white blue white blue white blue $k 4 5 6 4 5 6 4 5 6
Do Lab4 see example20

81

Create a list of the names of all the elements in the XML


<ul> { let $i := for $j in //* return name($j) for $k in $i return <li>{$k}</li> } </ul>

Output: FitnessCenter Member Name Member Name


see example20-a

82

Create a list of distinct FavoriteColor values


<ul> { let $source := doc("FitnessCenter.xml") let $colors := $source//FavoriteColor let $distinct := distinct-values($colors) for $i in $distinct return <li>{$i}</li> } </ul>

Output:

lightgrey lightblue lightyellow purple

see example20-b

83

Show the members for each favorite color


Desired Output: Members with lightgrey as their favorite color: Jeff Sally Emily Members with lightblue as their favorite color: David George Members with lightyellow as their favorite color: Roger Members with purple as their favorite color: Linda

84

Show the members for each favorite color


<ul> { let $source := doc("FitnessCenter.xml") let $colors := $source//FavoriteColor let $distinct := distinct-values($colors) for $i in $distinct return <li> Members with {$i} as their favorite color: <ul> { let $names := $source//Member[child::FavoriteColor eq $i]/Name for $j in $names return <li>{data($j)}</li>

} </ul> </li>
} </ul>
see example20-c

85

Alternate solution, using "where"


<ul> { let $source := doc("FitnessCenter.xml") let $colors := $source//FavoriteColor let $distinct := distinct-values($colors)

for $i in $distinct return <li> Members with {$i} as their favorite color: <ul> { for $j in $source//Member where $j/child::FavoriteColor eq $i return <li>{$j/data(Name)}</li> } </ul> </li>
} </ul>
see example20-d

86

Declaring variables
The top of an XQuery document is called the Prolog. In the Prolog you can declare variables, functions, namespaces, and import other XQuery documents and schemas.
declare variable $increase := 1.1; <html> <body> <table border="1"> <tr><th>Name</th><th>Old Rate</th><th>New Rate</th></tr> { for $i in //Member return <tr> <td>{$i/Name/text()}</td> <td>{if ($i/@level eq "platinum") then 500 else if ($i/@level eq "gold") then 450 else 400}</td> <td>{if ($i/@level eq "platinum") then 500 * $increase else if ($i/@level eq "gold") then 450 * $increase else 400 * $increase}</td> </tr> } </table> </body> </html>

see example21

87
<?xml version="1.0"?> <FitnessCenter> <Member level="platinum"> <Name>Jeff</Name> </Member> <Member level="gold"> <Name>David</Name> </Member> <Member level="platinum"> <Name>Roger</Name> </Member> <Member level="silver"> <Name>Stacey</Name> </Member> <Member level="gold"> <Name>Linda</Name> </Member> <Member level="platinum"> <Name>John</Name> </Member> </FitnessCenter>

declare variable $increase := 1.1; <html> <body> <table border="1"> <tr><th>Name</th><th>Old Rate</th><th>New Rate</th></tr> { for $i in //Member return <tr> <td>{$i/Name/text()}</td> <td>{if ($i/@level eq "platinum") then 500 else if ($i/@level eq "gold") then 450 else 400}</td> <td>{if ($i/@level eq "platinum") then 500 * $increase else if ($i/@level eq "gold") then 450 * $increase else 400 * $increase}</td> </tr> } </table> </body> </html>

FitnessCenter.xml

FitnessCenter.xq

Name Jeff David Roger Stacey Linda John

Old Rate 500 450 500 400 450 500

New Rate 550 495 550 440 495 550


see example21

88

Prolog, Body
An XQuery document is composed of an optional Prolog followed by the Body. Up until the last slide all of our examples have just had a Body (we had no Prolog).
Version Declaration Variable Declarations

xquery version="1.0" encoding="UTF-8";

Prolog

Function Declarations

Namespace Declarations

Body

declare variable $var := expr; declare variable $var := expr; ... declare function name (params) as type { expr }; declare function name (params) as type { expr }; declare namespace prefix = "URI"; declare namespace prefix = "URI"; ... <html> </html>

89

Use Semicolons in Prolog


xquery version="1.0" encoding="UTF-8"; declare variable $var := expr; declare variable $var := expr; ... declare function name (params) as type { expr }; declare function name (params) as type { expr }; declare namespace prefix = "URI"; declare namespace prefix = "URI"; ... <html> </html>

90

Multiple Variables
This is exactly like the last example except the sequence of Members are stored in a variable:
declare variable $members := //Member; declare variable $increase := 1.1; <html> <body> <table border="1"> <tr><th>Name</th><th>Old Rate</th><th>New Rate</th></tr> { for $i in $members return <tr> <td>{$i/Name/text()}</td> <td>{if ($i/@level eq "platinum") then 500 else if ($i/@level eq "gold") then 450 else 400}</td> <td>{if ($i/@level eq "platinum") then 500 * $increase else if ($i/@level eq "gold") then 450 * $increase else 400 * $increase}</td> </tr> } </table> </body> </html>

see example22

91

Using functions
namespace declaration
variable declaration

declare namespace ex = "http://www.example.org"; declare variable $multiplicand := 3;

function declaration

declare function ex:multiply ($num) { $num * $multiplicand };


<html> <body> <table border="1"> <tr><th>Old Value</th><th>New Value</th></tr> { for $i in //Number return <tr> <td>{data($i)}</td> <td>{ex:multiply($i)}</td> </tr> } </table> </body> </html>

see example23

92
<?xml version="1.0"?> <Numbers> <Number>0</Number> <Number>8</Number> <Number>23</Number> <Number>17</Number> <Number>5</Number> <Number>19</Number> <Number>44</Number> <Number>13</Number> <Number>78</Number> <Number>21</Number> <Number>2</Number> <Number>1</Number> <Number>15</Number> <Number>67</Number> <Number>99</Number> <Number>14</Number> <Number>8</Number> <Number>33</Number> <Number>50</Number> </Numbers>

Numbers.xml
declare namespace ex = "http://www.example.org"; declare variable $multiplicand := 3; declare function ex:multiply ($num) { $num * $multiplicand }; <html> <body> <table border="1"> <tr><th>Old Value</th><th>New Value</th></tr> { for $i in //Number return <tr> <td>{data($i)}</td> <td>{ex:multiply($i)}</td> </tr> } </table> </body> </html>

Numbers.xq
see example23

93

Function name must be a QName


All user-defined function names must be namespace qualified, i.e., the function name must be a QName (Qualified Name).
ex:multiply

94

Don't forget the semicolons


declare namespace ex = "http://www.example.org"; declare variable $multiplicand := 3;

declare function ex:multiply ($num) { $num * $multiplicand };


<html> <body> <table border="1"> <tr><th>Old Value</th><th>New Value</th></tr> { for $i in //Number return <tr> <td>{data($i)}</td> <td>{ex:multiply($i)}</td> </tr> } </table> </body> </html>

95

If you do forget ...


declare namespace ex = "http://www.example.org"; declare variable $multiplicand := 3;

declare function ex:multiply ($num) { $num * $multiplicand }


<html> ... </html>

forgot the semicolon here

Here's the error message you will get:


Error XQuery syntax error on line 10 of Numbers.xq in '... $num * $multiplicand } <': expected ";", found "<element>"

96

Square a number, n
declare namespace ex = "http://www.example.org";

Prolog

declare function ex:Square ($n) { $n * $n }; let $result := ex:Square(4)

Body

return $result

Do Lab5 see example23-c

97

Identity transform plus lcase


Write an XQuery function. Pass it XML. It converts all the element and attribute names to lower case.
<FitnessCenter> <Member level="platinum"> <Name>Jeff</Name> <FavoriteColor>lightgrey</FavoriteColor> </Member> <Member level="gold"> <Name>David</Name> <FavoriteColor>lightblue</FavoriteColor> </Member> <Member level="platinum"> <Name>Roger</Name> <FavoriteColor>lightyellow</FavoriteColor> </Member> </FitnessCenter> <fitnesscenter> <member> <name>Jeff</name> <favoritecolor>lightgrey</favoritecolor> </member> <member> <name>David</name> <favoritecolor>lightblue</favoritecolor> </member> <member> <name>Roger</name> <favoritecolor>lightyellow</favoritecolor> </member> </fitnesscenter>

98

Here's the XQuery


declare namespace ex = "http://www.example.org"; declare function ex:identity-plus-lcase ($seq) { for $i in $seq return if ($i[self::*]) then element {lower-case(name($i))} {ex:identity-plus-lcase($i/child::node())} else text {$i} }; ex:identity-plus-lcase(doc('FitnessCenter.xml')/*)
see example23-a

99

Oops! Forgot the attributes


The function lost the attributes. The next slide shows an XQuery function that doesn't loose the attributes.

100

Identity transform plus lcase


declare namespace ex = "http://www.example.org"; declare function ex:identity-plus-lcase ($seq) { for $i in $seq return if ($i[self::*]) then element {lower-case(name($i))} { for $j in $i/@* return attribute {lower-case(name($j))} {data($j)}, ex:identity-plus-lcase($i/child::node()) } else text {$i} }; ex:identity-plus-lcase(doc('FitnessCenter.xml')/*)
see example23-b

101

Modules
You can create files just containing a Prolog. These are called modules. Example: I moved the Prolog in a previous example into a separate file:
module namespace m = "http://www.multiplication.org"; declare variable $m:multiplicand := 3;

Multiplication-Module.xqm

declare function m:multiply ($num) { $num * $m:multiplicand };

import module namespace m = "http://www.multiplication.org" at "Multiplication-Module.xqm"; <html> <body> <table border="1"> <tr><th>Old Value</th><th>New Value</th></tr> { for $i in //Number return <tr> <td>{data($i)}</td> <td>{m:multiply($i)}</td> </tr> } </table> </body> </html>

Numbers.xq

see example24

102

A Module defines a targetNamespace


Namespace prefix The module's targetNamespace

module namespace m = "http://www.multiplication.org"; declare variable $m:multiplicand := 3; declare function m:multiply ($num) { $num * $m:multiplicand };

103

Module variables must be QNames


module namespace m = "http://www.multiplication.org"; declare variable $m:multiplicand := 3; declare function m:multiply ($num) { $num * $m:multiplicand };

Variables without a qualifier are in "no namespace." Variable declarations that have no namespace prefix may appear only in the XQuery Body.

104

import the module


Identify the namespace of the module URL location of the module
import module namespace m = "http://www.multiplication.org" at "Multiplication-Module.xqm"; <html> <body> <table border="1"> <tr><th>Old Value</th><th>New Value</th></tr> { for $i in //Number return <tr> <td>{data($i)}</td> <td>{m:multiply($i)}</td> </tr> } </table> </body> </html>

105

Namespaces must match


module namespace m = "http://www.multiplication.org"; declare variable $m:multiplicand := 3; declare function m:multiply ($num) { $num * $m:multiplicand };

The prefixes don't have to match

import module namespace m = "http://www.multiplication.org" at "Multiplication-Module.xqm"; <html> <body> <table border="1"> <tr><th>Old Value</th><th>New Value</th></tr> { for $i in //Number return <tr> <td>{data($i)}</td> <td>{m:multiply($i)}</td> </tr> } </table> </body> </html>

106

Filename Suffix
Use .xq as the filename suffix for XQuery files. Use .xqm as the filename suffix for XQuery Module files. By adopting this convention you will be able to quickly scan a folder and see which files are executable (the .xq files) and which are not (the .xqm files).
Do Lab6

107

Using Multiple Modules


module namespace m = "http://www.multiplication.org"; declare variable $m:multiplicand := 3; declare function m:multiply ($num) { $num * $m:multiplicand }; module namespace a = "http://www.addition.org"; declare variable $a:add-value := 10; declare function a:add ($num) { $num + $a:add-value };

Multiplication-Module.xqm

Addition-Module.xqm

import module namespace m = "http://www.multiplication.org" at "Multiplication-Module.xqm"; import module namespace a = "http://www.addition.org" at "Addition-Module.xqm"; <html> <body> <table border="1"> <tr><th>Old Value</th><th>* Value</th><th>+ Value</th></tr> { for $i in //Number return <tr> <td>{data($i)}</td> <td>{m:multiply($i)}</td> <td>{a:add($i)}</td> </tr> } </table> </body> </html>

Numbers.xq

see example25

108

Single Module, Multiple Functions


module namespace m = "http://www.math.org"; declare variable $m:multiplicand := 3; declare function m:multiply ($num) { $num * $m:multiplicand }; declare variable $m:add-value := 10; declare function m:add ($num) { $num + $m:add-value };

Rule: a file can contain only one module.

Math-Module.xqm
import module namespace m = "http://www.math.org" at "Math-Module.xqm"; <html> <body> <table border="1"> <tr><th>Old Value</th><th>* Value</th><th>+ Value</th></tr> { for $i in //Number return <tr> <td>{data($i)}</td> <td>{m:multiply($i)}</td> <td>{m:add($i)}</td> </tr> } </table> </body> </html>

Numbers.xq

see example26

109

Type Checking
import module namespace m = "http://www.math.org" at "Math-Module.xqm"; declare namespace xsd = "http://www.w3.org/2001/XMLSchema"; <html> <body> <table border="1"> <tr><th>Old Value</th><th>* Value</th><th>+ Value</th></tr> { for $i in //Number return <tr> <td>{xsd:integer($i)}</td> <td>{xsd:integer(m:multiply($i))}</td> <td>{xsd:integer(m:add($i))}</td> </tr> } </table> </body> </html>

By wrapping a value within a datatype you are instructing the XQuery processor to validate that the value is of that data type.

see example27

Type checking against user-defined types


<?xml version="1.0"?> <Chapters> <li>Chapter1</li> <li>Chapter2</li> <li>Chapter3</li> <li>Chapter4</li> <li>Chapter5</li> <li>Chapter6</li> <li>Chapter7</li> <li>Chapter8</li> <li>Chapter9</li> </Chapters>
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.books.org" xmlns="http://www.books.org" elementFormDefault="qualified"> <xsd:simpleType name="Chapter"> <xsd:restriction base="xsd:string"> <xsd:pattern value="Chapter\d"/> </xsd:restriction> </xsd:simpleType> </xsd:schema>

110

UserDefinedSimpleTypes.xsd
import schema namespace bk = "http://www.books.org" at "UserDefinedSimpleTypes.xsd"; <html> <body> <table border="1"> <tr><th>Chapter</th></tr> { for $i in //li return <tr> <td>{bk:Chapter($i)}</td> </tr> } </table> </body> </html>

ChapterList.xml

CheckChapterList.xq
see example28

111

import XML Schema


Identify the targetNamespace of the XML Schema
URL location of the XML Schema

import schema namespace bk = "http://www.books.org" at "UserDefinedSimpleTypes.xsd"; <html> <body> <table border="1"> <tr><th>Chapter</th></tr> { for $i in //li return <tr> <td>{bk:Chapter($i)}</td> </tr> } </table> </body> </html>

112

Type checking against user-defined types that are in no namespace


<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">

<?xml version="1.0"?> <Chapters> <li>Chapter1</li> <li>Chapter2</li> <li>Chapter3</li> <li>Chapter4</li> <li>Chapter5</li> <li>Chapter6</li> <li>Chapter7</li> <li>Chapter8</li> <li>Chapter9</li> </Chapters>

<xsd:simpleType name="Chapter"> <xsd:restriction base="xsd:string"> <xsd:pattern value="Chapter\d"/> </xsd:restriction> </xsd:simpleType> </xsd:schema>

UserDefinedSimpleTypes.xsd

import schema default element namespace "" at "UserDefinedSimpleTypes.xsd"; <html> <body> <table border="1"> <tr><th>Chapter</th></tr> { for $i in //li return <tr> <td>{$i cast as Chapter}</td> </tr> } </table> </body> </html>

ChapterList.xml

Do this

CheckChapterList.xq
see example29

113

$var cast as datatype


Import an XML Schema where the elements and types are in no namespace
import schema default element namespace "" at "UserDefinedSimpleTypes.xsd"; <html> <body> <table border="1"> <tr><th>Chapter</th></tr> { for $i in //li return <tr> <td>{$i cast as Chapter}</td> </tr> } </table> </body> </html>

Type cast the value of $i to the user-defined type Chapter.

114

Comments
XQuery uses the same syntax for comments as XPath 2.0
<ul>
{ let $source := doc("FitnessCenter.xml") let $colors := $source//FavoriteColor let $distinct := distinct-values($colors) for $i in $distinct (: Show distinct FavoriteColor values :) return <li>{$i}</li> } </ul>

115

Output Text
In this tutorial we have seen XQueries that created (X)HTML and XQueries that created XML. Now let's see an XQuery that creates text.

116
<?xml version="1.0" encoding="UTF-8"?> <bookstore storename="The ABC Book Store"> <book> <title>The Origin of Wealth</title> <author>Eric D. Beinhocker</author> <date>2006</date> <ISBN>1-57851-777-X</ISBN> <publisher>Harvard Business School Press</publisher> <cost currency="USD">29.95</cost> </book> </bookstore>

XML

XQuery

The ABC Book Store The Origin of Wealth/Eric D. Beinhocker/2006/1-57851-777-X/Harvard Business School Press/29.95 DOM Scripting/Jeremy Keith/2005/1-59059-533-5/friends of ed/34.99 Guns, Germs, and Steel/Jared Diamond/2005/0-393-06131-0/W. W. Norton & Company, Ltd./24.99

Text

Economics in One Lesson/Henry Hazlitt/1946/0-517-54823-2/Three Rivers Press/11.00 How to Read a Book/Mortimer J. Adler/Charles Van Doren/1940/0-671-21280-x/Simon & Schuster, Inc./15.00 Don't Make Me Think/Steve Krug/2006/0-321-34475-8/New Riders/40.00 Bulletproof Ajax/Jeremy Keith/2007/0-321-47266-7/New Riders/34.99

117

let $source := doc("bookstore.xml")

return ( string($source/bookstore/@storename), for $i in $source//book return ( "&#xA;", (: Hex A is newline :) string-join( ( string($i/title), string($i/author[1]), string($i/date), string($i/ISBN), string($i/publisher), string($i/cost[@currency='USD']) ), '/' ) ) )

see example30

118

Can XQuery produce non-XML output?


Hi Folks, Every time I run an XQuery, the output has an XML declaration at the top, even if the output is not XML, e.g., <?xml version="1.0" encoding="UTF-8"?>The ABC Book Store The Origin of Wealth/Eric D. Beinhocker/2006/1-57851-777-X/Harvard Business School Press/29.95 DOM Scripting/Jeremy Keith/2005/1-59059-533-5/friends of ed/34.99 Guns, Germs, and Steel/Jared Diamond/2005/0-393-06131-0/W. W. Norton &amp; Company, Ltd./24.99 Economics in One Lesson/Henry Hazlitt/1946/0-517-54823-2/Three Rivers Press/11.00 How to Read a Book/Mortimer J. Adler/1940/0-671-21280-x/Simon &amp; Schuster, Inc./15.00 Don't Make Me Think/Steve Krug/2006/0-321-34475-8/New Riders/40.00 Bulletproof Ajax/Jeremy Keith/2007/0-321-47266-7/New Riders/34.99 Is there a way to specify in the XQuery the type of output (XML, text, HTML)? Is there a way to avoid the output having an XML declaration at the top? /Roger

119

>Is there a way to avoid the output having an XML declaration at the top?

Yes, by engaging properties of serialization:

http://www.w3.org/TR/2007/REC-xslt-xquery-serialization-20070123/

Not all processors support serialization, and those that do, do not support all serialization methods or properties of serialization.

The way one specifies serialization in XQuery is typically through options. Here's how to specify text output for two different products:

Using Saxon: declare namespace saxon = "http://saxon.sf.net/";

declare option saxon:output "indent=no";


declare option saxon:output "method=text";

Using eXist: declare namespace exist = "http://exist.sourceforge.net/NS/exist"; declare option exist:serialize "method=text indent=no";

120

declare namespace saxon = "http://saxon.sf.net/"; declare option saxon:output "indent=no"; declare option saxon:output "method=text"; let $source := doc("bookstore.xml") return ( string($source/bookstore/@storename), for $i in $source//book return ( "&#xA;", string-join( ( string($i/title), string($i/author[1]), string($i/date), string($i/ISBN), string($i/publisher), string($i/cost[@currency='USD']) ), '/' ) ) )

Do Lab7 see example31

121

XQueryX
XQueryX is an XML representation of an XQuery. It is not convenient for humans to read and write, but it is easy for programs to parse, and because XQueryX is represented in XML, standard XML tools can be used to create, interpret, or modify queries.

122

XQuery
<bib> { for $b in doc("http://bstore1.example.com/bib.xml")/bib/book where $b/publisher = "Addison-Wesley" and $b/@year > 1991 return <book year="{ $b/@year }"> { $b/title } </book> } </bib>

123

XQueryX

http://www.w3.org/TR/xqueryx/#Example1-XQueryX

You might also like