Top Banner
1 Roger L. Costello 16 June 2010 XQuery http:// www.w3.org/TR/xquery /
123
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 1 Roger L. Costello 16 June 2010 XQuery

1

Roger L. Costello16 June 2010

XQuery

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

Page 2: 1 Roger L. Costello 16 June 2010 XQuery

2

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/

Page 3: 1 Roger L. Costello 16 June 2010 XQuery

3

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

Page 4: 1 Roger L. Costello 16 June 2010 XQuery

4

Usage

XQueryProcessor

FitnessCenter.xml

FitnessCenter.xq

HTML, XML, text

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

Page 5: 1 Roger L. Costello 16 June 2010 XQuery

5

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

Page 6: 1 Roger L. Costello 16 June 2010 XQuery

6

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

Page 7: 1 Roger L. Costello 16 June 2010 XQuery

7

Execute XQuery in Oxygen XML (cont.)

1. Choose XQuery transformation

2. Click on New

Page 8: 1 Roger L. Costello 16 June 2010 XQuery

8

Execute XQuery in Oxygen XML (cont.)

1. Select the XML file.

2. Click on OK

Page 9: 1 Roger L. Costello 16 June 2010 XQuery

9

Execute XQuery in Oxygen XML (cont.)

Click on OK

Page 10: 1 Roger L. Costello 16 June 2010 XQuery

10

1. Click on this

2. Results are shown here

Page 11: 1 Roger L. Costello 16 June 2010 XQuery

11

XQuery = XPath 2.0 + more

XQuery

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

XPath 2.0

XPath 1.0

Page 12: 1 Roger L. Costello 16 June 2010 XQuery

12

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

Query this XML

We will use this XML document throughout the tutorial, so spend a minute or two familiarizing yourself with it.

It is FitnessCenter.xml in the example01 folder. Please load it into Oxygen XML.

Page 13: 1 Roger L. Costello 16 June 2010 XQuery

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>

Page 14: 1 Roger L. Costello 16 June 2010 XQuery

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.

Page 15: 1 Roger L. Costello 16 June 2010 XQuery

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>

Page 16: 1 Roger L. Costello 16 June 2010 XQuery

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.

Page 17: 1 Roger L. Costello 16 June 2010 XQuery

17

Note the curly braces within curly braces

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

Page 18: 1 Roger L. Costello 16 June 2010 XQuery

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 XQueryexpression that you want evaluated, you must wrap theexpression within curly braces.

Page 19: 1 Roger L. Costello 16 June 2010 XQuery

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>

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

Output:JeffDavidRoger

see example02

No curly brace, no evaluation!

Page 20: 1 Roger L. Costello 16 June 2010 XQuery

20

Structure of an XQuery Document

Prolog(optional)

Body(required)

Page 21: 1 Roger L. Costello 16 June 2010 XQuery

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

,

Page 22: 1 Roger L. Costello 16 June 2010 XQuery

22

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

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

FitnessCenter.xq

see example01

<html> <head> <title>Member Names</title> </head> <body> <ul> <li>Jeff</li> <li>David</li> <li>Roger</li> </ul> </body></html>

Evaluate the XQuery

XQuery embedded in HTML

Page 23: 1 Roger L. Costello 16 June 2010 XQuery

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.

Page 24: 1 Roger L. Costello 16 June 2010 XQuery

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>

Page 25: 1 Roger L. Costello 16 June 2010 XQuery

25

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

FitnessCenter.xq

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

Evaluate the XQuery

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

Explicit Input

Page 26: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 27: 1 Roger L. Costello 16 June 2010 XQuery

27

Getting the value of an element versus copying an element

XSLT XQuery

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

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

Lessons Learned:1. In XQuery, if you want to get the value of an element either:

use the text() function, orwrap the element name within the string() function, orwrap 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.

Page 28: 1 Roger L. Costello 16 June 2010 XQuery

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

Output:JeffDavidRoger

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

Output:Jeff David Roger

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

Output:Jeff David Roger

see example03

for $i in //Member return $i/Name

Output:<Name>Jeff</Name> <Name>David</Name> <Name>Roger</Name>

Page 29: 1 Roger L. Costello 16 June 2010 XQuery

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 )

Page 30: 1 Roger L. Costello 16 June 2010 XQuery

30

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

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

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 declaredFailed to compile query: XQuery syntax errorQuery processing failed: net.sf.saxon.xpath.StaticError: XQuery syntax error

Here's the error message that you get:

Page 31: 1 Roger L. Costello 16 June 2010 XQuery

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>

see example04

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>

Page 32: 1 Roger L. Costello 16 June 2010 XQuery

32

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

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

FitnessCenter.xq

<?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> </Member> </result></test>

Evaluate the XQuery

XQuery embedded in XML

Page 33: 1 Roger L. Costello 16 June 2010 XQuery

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!

Page 34: 1 Roger L. Costello 16 June 2010 XQuery

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> …</FitnessCenter>

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

xmlns:gym="http://www.gym.com">

<head>

</head>

<body>

<h1>Fitness Center</h1>

<div id="fitness">

{

for $i in //gym:Member return

}

</div>

</body>

</html>

Page 35: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 36: 1 Roger L. Costello 16 June 2010 XQuery

36

Specifying HTML outputwith 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>

<!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>

Evaluate the XQuery

Page 37: 1 Roger L. Costello 16 June 2010 XQuery

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.

Page 38: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 39: 1 Roger L. Costello 16 June 2010 XQuery

39

Creating Attributes

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

Recall $i/Name returns a copy of the <Name> element:

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

Page 40: 1 Roger L. Costello 16 June 2010 XQuery

40

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

Equivalent

see example05

Do Lab1

Page 41: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 42: 1 Roger L. Costello 16 June 2010 XQuery

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 parenthesesand separate the expressions by commas.

see example05

Page 43: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 44: 1 Roger L. Costello 16 June 2010 XQuery

44

Create Element Valuefrom 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>

Page 45: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 46: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 47: 1 Roger L. Costello 16 June 2010 XQuery

47

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

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

FitnessCenter.xq

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

MemberInfo.xml

see example07

Do Lab2

Page 48: 1 Roger L. Costello 16 June 2010 XQuery

48<?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

FitnessCenter.xq

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

Members.xml

???

Page 49: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 50: 1 Roger L. Costello 16 June 2010 XQuery

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>

Page 51: 1 Roger L. Costello 16 June 2010 XQuery

51

element {name} {value}

Here are examples of using the element keyword todynamically create an element:

see example09

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>

Page 52: 1 Roger L. Costello 16 June 2010 XQuery

52

Another Example

element {name(/*/*[1])} {/*/*[1]/*}

Output:<Member>  <Name>Jeff</Name>   <FavoriteColor>lightgrey</FavoriteColor> </Member>

see example09

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

Page 53: 1 Roger L. Costello 16 June 2010 XQuery

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>

see example10

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

Page 54: 1 Roger L. Costello 16 June 2010 XQuery

54

Sequence values are always separated by commas

<aircraft> { element altitude {12000}, element speed {160} }</aircraft>

Notice the comma.It separates the twoelement sequencevalues.

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

see example11

Page 55: 1 Roger L. Costello 16 June 2010 XQuery

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 errorQuery processing failed: net.sf.saxon.xpath.StaticError: XQuery syntax error

Page 56: 1 Roger L. Costello 16 June 2010 XQuery

56

attribute {name} {value}and

text {value}Here are examples of using the attribute keyword andthe 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

Page 57: 1 Roger L. Costello 16 June 2010 XQuery

57

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

separate the altitude element from thespeed element.

separate the units attribute from thetext node.

separate the units attribute from thetext node.

REMINDER: SEQUENCE VALUES ARE ALWAYS SEPARATED BY COMMAS!

Page 58: 1 Roger L. Costello 16 June 2010 XQuery

58

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

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

MembershipLevelCosts.xml

???

FitnessCenter.xml

Page 59: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 60: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 61: 1 Roger L. Costello 16 June 2010 XQuery

61

Computed Document Constructor

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

Page 62: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 63: 1 Roger L. Costello 16 June 2010 XQuery

63

Summary of Computed Constructors

document {value}

element {name} {value}

attribute {name} {value}

text {value}

The name of the element is computed.

The name of the attribute is computed.

A document node is created.

A text node is created.

Page 64: 1 Roger L. Costello 16 June 2010 XQuery

64

Terminology

<altitude>12000</altitude>

This is called a direct element constructor:

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

This is called a computed element constructor:

Page 65: 1 Roger L. Costello 16 June 2010 XQuery

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>

see example15-a

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

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

Page 66: 1 Roger L. Costello 16 June 2010 XQuery

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} }

Page 67: 1 Roger L. Costello 16 June 2010 XQuery

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.

XMLXQuery

Page 68: 1 Roger L. Costello 16 June 2010 XQuery

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>

see example15

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

Page 69: 1 Roger L. Costello 16 June 2010 XQuery

69

Whitespace• By default whitespace that occurs around an

evaluated expression is stripped.

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

Output:<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

Page 70: 1 Roger L. Costello 16 June 2010 XQuery

70

XQuery can sort values

• XPath provides no way to sort values.

• With XQuery you can sort values.

Page 71: 1 Roger L. Costello 16 June 2010 XQuery

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 youwant the data sorted. In this example Ispecified that I want the Members sortedusing the Name field in ascending order.

see example17

Page 72: 1 Roger L. Costello 16 June 2010 XQuery

72

Sort the Numbers <= 20

Output:• 0• 1• 2• 5• 8• 8• 13• 14• 15• 17• 19

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

Numbers.xq

see example18

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

Page 73: 1 Roger L. Costello 16 June 2010 XQuery

73

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

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

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

Numbers_v2.xq

see example18

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

Output:• 0• 1• 2• 5• 8• 8• 13• 14• 15• 17• 19

Page 74: 1 Roger L. Costello 16 June 2010 XQuery

74

Equivalent

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

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

Page 75: 1 Roger L. Costello 16 June 2010 XQuery

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>

<?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 datais sortedby id value

This datais sortedby Age

David 39Jeff 35Linda 40Roger 32Stacey 25

This datais sortedby Name

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

Join each Member'sName with their Age

Page 76: 1 Roger L. Costello 16 June 2010 XQuery

76

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

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

see example19

MemberInfo.xq

MemberAges.xmlMemberNames.xml

Page 77: 1 Roger L. Costello 16 June 2010 XQuery

77

for $i in expr1 let $j := expr2 where expr3 order by expr4 return expr5

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

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

see example19

MemberInfo_v2.xq

This is an alternate(equivalent) solution

Page 78: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 79: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 80: 1 Roger L. Costello 16 June 2010 XQuery

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>

$i $j $k1 red white blue 41 red white blue 51 red white blue 62 red white blue 42 red white blue 52 red white blue 63 red white blue 43 red white blue 53 red white blue 6

Output:

see example20

Do Lab4

Page 81: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 82: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 83: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 84: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 85: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 86: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 87: 1 Roger L. Costello 16 June 2010 XQuery

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 Old Rate New RateJeff 500 550David 450 495Roger 500 550Stacey 400 440Linda 450 495John 500 550

see example21

Page 88: 1 Roger L. Costello 16 June 2010 XQuery

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

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>

VariableDeclarations

FunctionDeclarations

Body

Prolog

NamespaceDeclarations

VersionDeclaration

Page 89: 1 Roger L. Costello 16 June 2010 XQuery

89

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>

Use Semicolons in Prolog

Page 90: 1 Roger L. Costello 16 June 2010 XQuery

90

Multiple Variables

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

This is exactly like the last example except the sequence of Members are stored in a variable:

Page 91: 1 Roger L. Costello 16 June 2010 XQuery

91

Using functionsdeclare 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>

namespace declaration

variable declaration

function declaration

see example23

Page 92: 1 Roger L. Costello 16 June 2010 XQuery

92

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>

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

Numbers.xqsee example23

Page 93: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 94: 1 Roger L. Costello 16 June 2010 XQuery

94

Don't forget the semicolonsdeclare 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>

Page 95: 1 Roger L. Costello 16 June 2010 XQuery

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>

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

forgot the semicolon here

Here's the error message you will get:

Page 96: 1 Roger L. Costello 16 June 2010 XQuery

96

Square a number, n

declare namespace ex = "http://www.example.org";

declare function ex:Square ($n){ $n * $n };

let $result := ex:Square(4)

return $result

Do Lab5

see example23-c

Prolog

Body

Page 97: 1 Roger L. Costello 16 June 2010 XQuery

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>

Page 98: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 99: 1 Roger L. Costello 16 June 2010 XQuery

99

Oops! Forgot the attributes

• The function lost the attributes.

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

Page 100: 1 Roger L. Costello 16 June 2010 XQuery

100

Identity transform plus lcasedeclare 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

Page 101: 1 Roger L. Costello 16 June 2010 XQuery

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;

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

Multiplication-Module.xqm

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

Page 102: 1 Roger L. Costello 16 June 2010 XQuery

102

A Module defines a targetNamespace

module namespace m = "http://www.multiplication.org";

declare variable $m:multiplicand := 3;

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

The module'stargetNamespace

Namespaceprefix

Page 103: 1 Roger L. Costello 16 June 2010 XQuery

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 prefixmay appear only in the XQuery Body.

Page 104: 1 Roger L. Costello 16 June 2010 XQuery

104

import 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>

URL locationof the module

Identify the namespaceof the module

Page 105: 1 Roger L. Costello 16 June 2010 XQuery

105

Namespaces must matchmodule namespace m = "http://www.multiplication.org";

declare variable $m:multiplicand := 3;

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>

The prefixes don't have to match

Page 106: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 107: 1 Roger L. Costello 16 June 2010 XQuery

107

Using Multiple Modules

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>

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

Numbers.xq see example25

Page 108: 1 Roger L. Costello 16 June 2010 XQuery

108

Single Module, Multiple Functions

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.xqsee example26

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

Math-Module.xqm

Rule: a file can containonly one module.

Page 109: 1 Roger L. Costello 16 June 2010 XQuery

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>

see example27

By wrapping avalue within adatatype you areinstructing theXQuery processorto validate thatthe value is of thatdata type.

Page 110: 1 Roger L. Costello 16 June 2010 XQuery

110

Type checking against user-defined types

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>

CheckChapterList.xq

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

ChapterList.xml

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

UserDefinedSimpleTypes.xsd

see example28

Page 111: 1 Roger L. Costello 16 June 2010 XQuery

111

import XML Schema

URL locationof the XML Schema

Identify the targetNamespaceof 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>

Page 112: 1 Roger L. Costello 16 June 2010 XQuery

112

Type checking against user-defined types that 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>

CheckChapterList.xq

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

ChapterList.xml

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

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

</xsd:schema>

UserDefinedSimpleTypes.xsd

see example29

Do this

Page 113: 1 Roger L. Costello 16 June 2010 XQuery

113

$var cast as datatype

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>

Import an XML Schema where the elements and types are in no namespace

Type cast the valueof $i to the user-definedtype Chapter.

Page 114: 1 Roger L. Costello 16 June 2010 XQuery

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>

Page 115: 1 Roger L. Costello 16 June 2010 XQuery

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.

Page 116: 1 Roger L. Costello 16 June 2010 XQuery

116

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

XQuery

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

Text

Page 117: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 118: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 119: 1 Roger L. Costello 16 June 2010 XQuery

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

Page 120: 1 Roger L. Costello 16 June 2010 XQuery

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']) ), '/' ) ) )

see example31

Do Lab7

Page 121: 1 Roger L. Costello 16 June 2010 XQuery

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.

Page 122: 1 Roger L. Costello 16 June 2010 XQuery

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>

Page 123: 1 Roger L. Costello 16 June 2010 XQuery

123

XQueryX

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