Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Roger L. Costello 16 June 2010 XQuery

Similar presentations


Presentation on theme: "1 Roger L. Costello 16 June 2010 XQuery"— Presentation transcript:

1 1 Roger L. Costello 16 June 2010 XQuery http://www.w3.org/TR/xquery/ http://www.w3.org/TR/xquery/

2 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/http://www.xfront.com/xpath/

3 3 XQuery Mailing List There is a world-wide XQuery mailing list, talk@x-query.com talk@x-query.com Here's the web page where you can subscribe: http://www.x-query.com/mailman/listinfo/talk http://www.x-query.com/mailman/listinfo/talk

4 4 Usage XQuery Processor FitnessCenter.xml FitnessCenter.xq HTML, XML, text Note: The file extension may be.xq or.xquery

5 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

6 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

7 7 Execute XQuery in Oxygen XML (cont.) 1. Choose XQuery transformation 2. Click on New

8 8 Execute XQuery in Oxygen XML (cont.) 1. Select the XML file. 2. Click on OK

9 9 Execute XQuery in Oxygen XML (cont.) Click on OK

10 10 1. Click on this 2. Results are shown here

11 11 XQuery = XPath 2.0 + more XQuery XQuery is a superset of XPath 2.0, which is a superset of XPath 1.0 XPath 2.0 XPath 1.0

12 12 Jeff lightgrey David lightblue Roger lightyellow 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.

13 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., {for $i in //Member return $i/Name/text()}

14 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 Linda With XQuery you can create nodes.

15 15 Select each member's name and wrap each name in a list item,, element: {for $i in //Member return {$i/Name/text()} }

16 16 Result Jeff David Roger The XQuery created elements! And the XQuery filled the elements with data from the XML document.

17 17 Note the curly braces within curly braces {for $i in //Member return {$i/Name/text()} }

18 18 Rule for using curly braces {for $i in //Member return {$i/Name/text()} } Whenever you have an element whose contents is an XQuery expression that you want evaluated, you must wrap the expression within curly braces.

19 19 for $i in //Member return {$i/Name/text()} Output: Jeff David Roger for $i in //Member return $i/Name/text() Output: $i/Name/text() for $i in //Member return $i/Name/text() Output: JeffDavidRoger see example02 No curly brace, no evaluation!

20 20 Structure of an XQuery Document Prolog (optional) Body (required)

21 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 22 Member Names Member Names {for $i in //Member return {$i/Name/text()} } Jeff lightgrey David lightblue Roger lightyellow FitnessCenter.xml FitnessCenter.xq see example01 Member Names Jeff David Roger Evaluate the XQuery XQuery embedded in HTML

23 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 24 Implicit vs Explicit Input This XQuery queries an implicit XML document: for $i in //Member return {$i/Name/text()} This XQuery explicitly specifies the XML document to be queried: for $i in doc('FitnessCenter.xml')//Member return {$i/Name/text()}

25 25 Member Names Member Names {for $i in doc('FitnessCenter.xml')//Member return {$i/Name/text()} } FitnessCenter.xq … Jeff David Roger Evaluate the XQuery Jeff lightgrey David lightblue Roger lightyellow FitnessCenter.xml Explicit Input

26 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 27 Getting the value of an element versus copying an element XSLTXQuery $i/Name/text() or string($i/Name) or data($i/Name) $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.

28 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: Jeff David Roger

29 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 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 declared Failed to compile query: XQuery syntax error Query processing failed: net.sf.saxon.xpath.StaticError: XQuery syntax error Here's the error message that you get:

31 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 {("Name = ", $i/Name/text(), " FavoriteColor = ", $i/FavoriteColor/text())} Output: Name = Jeff FavoriteColor = lightgrey Name = David FavoriteColor = lightblue Name = Roger FavoriteColor = lightyellow see example04 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 /Member>

32 32 { for $i in //Member return {("Name = ", $i/Name/text())} {("FavoriteColor = ", $i/FavoriteColor/text())} } Jeff lightgrey David lightblue Roger lightyellow FitnessCenter.xml FitnessCenter.xq Name = Jeff FavoriteColor = lightgrey Name = David FavoriteColor = lightblue Name = Roger FavoriteColor = lightyellow Evaluate the XQuery XQuery embedded in XML

33 33 Default Namespace … Fitness Center { for $i in //Member return … } Trying to iterate through elements in the default (XHTML) namespace!

34 34 Rule: put XML in a namespace Jeff lightgrey … <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" xmlns:gym="http://www.gym.com"> … Fitness Center { for $i in //gym:Member return … }

35 35 DOCTYPE Declaration <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">... 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 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"; … <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">... Evaluate the XQuery

37 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 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 39 Creating Attributes for $i in //Member return $i/Name Output: Jeff David Roger Recall $i/Name returns a copy of the element: When used in assigning an attribute a value, $i/Name returns the value of the element: for $i in //Member return Output:

40 40 for $i in //Member return Output: for $i in //Member return Output: for $i in //Member return Output: Equivalent see example05 Do Lab1

41 41 Creating Attributes (cont.) $i/@id returns an attribute-value pair that then gets added to the enclosing element. for $i in //Member return {$i/@id} Output:

42 42 Create 2 Attributes for $i in //Member return {($i/@id, $i/@level)} Output: Remember to wrap the sequence in parentheses and separate the expressions by commas. see example05

43 43 Creating 3 Attributes { for $i in //Member return {($i/@id, $i/@level)} } Output: see example05

44 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 {data($i/@id)} Output: 1 2 3

45 45 Equivalent for $i in //Member return {data($i/@id)} Output: 1 2 3 for $i in //Member return {string($i/@id)} Output: 1 2 3 see example05

46 46 Create Element and Attribute for $i in //Member return {($i/@id, data($i/@level)))} Output: platinum gold platinum see example05

47 47 { for $i in //Member return $i/Name } { for $i in //Member return $i/FavoriteColor } Jeff lightgrey David lightblue Roger lightyellow FitnessCenter.xml FitnessCenter.xq Jeff David Roger lightgrey lightblue lightyellow MemberInfo.xml see example07 Do Lab2

48 48 Jeff lightgrey David lightblue Roger lightyellow FitnessCenter.xml FitnessCenter.xq Jeff Roger David Members.xml ???

49 49 Non-Extensible Solution { for $i in //Member[@level eq "platinum"] return $i/Name } { for $i in //Member[@level eq "gold"] return $i/Name } This XQuery document hardcodes the elements and. 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 50 Here's what we desire { 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 }

51 51 element {name} {value} Here are examples of using the element keyword to dynamically create an element: see example09 element {"FavoriteColor"} {"blue"} Output: blue element {"Numbers"} {1 to 10} Output: 1 2 3 4 5 6 7 8 9 10

52 52 Another Example element {name(/*/*[1])} {/*/*[1]/*} Output: Jeff lightgrey 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."

53 53 Solving the problem using a computed element constructor { for $i in distinct-values(//Member/@level) return element {string($i)} { for $j in //Member[@level eq $i] return $j/Name } see example10 The element name is computed using the value of $i. This is called a computed element constructor.

54 54 Sequence values are always separated by commas { element altitude {12000}, element speed {160} } Notice the comma. It separates the two element sequence values. Output: 12000 160 see example11

55 55 If you forget the comma... { element altitude {12000} element speed {160} } 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 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: { element {"altitude"} { attribute {"units"} {"feet"}, text {12000} }, element {"speed"} { attribute {"units"} {"knots"}, text {160} } Output: 12000 160 see example12

57 57 Use commas! { element {"altitude"} { attribute {"units"} {"feet"}, text {12000} }, element {"speed"} { attribute {"units"} {"knots"}, text {160} } separate the altitude element from the speed element. separate the units attribute from the text node. separate the units attribute from the text node. REMINDER: SEQUENCE VALUES ARE ALWAYS SEPARATED BY COMMAS!

58 58 Jeff 500 David 400 Roger 500 FitnessCenter.xq MembershipLevelCosts.xml ??? FitnessCenter.xml

59 59 FitnessCenter.xq { for $i in distinct-values(//Member/@level) return element {"level"} { attribute {$i} {//Member[@level eq $i][1]/MembershipFee} } Output: see example13

60 60 Computed Attribute Constructor { for $i in distinct-values(//Member/@level) return element {"level"} { attribute {$i} {//Member[@level eq $i][1]/MembershipFee} } The attribute name is computed using the value of $i. This is called a computed attribute constructor. Do Lab3

61 61 Computed Document Constructor This is used to create a document node: document {value}

62 62 document {value} document { element {"aircraft"} { element {"altitude"} { attribute {"units"} {"feet"}, text {12000} }, element {"speed"} { attribute {"units"} {"knots"}, text {160} } Output: 12000 160 see example14

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

64 64 Terminology 12000 This is called a direct element constructor: element {"altitude"} { text {12000} } This is called a computed element constructor:

65 65 Not XML element {"altitude"} { attribute {"units"} {"feet"}, text {12000} }, element {"speed"} { attribute {"units"} {"knots"}, text {160} } Output: 12000 160 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.

66 66 No XML Declaration Do not put an XML declaration at the top of your XQuery document. element {"altitude"} { attribute {"units"} {"feet"}, text {12000} }, element {"speed"} { attribute {"units"} {"knots"}, text {160} }

67 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. XML XQuery

68 68 Do not escape " " {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"} see example15 Output: 1 < 2 is TRUE, 1 > 2 is FALSE

69 69 Whitespace By default whitespace that occurs around an evaluated expression is stripped. hi {"hi"} {"hi"} {1 to 10} {"hi"},{"there"} {" "} {1,2,3} {1}{2}{3} Output: hi 1 2 3 4 5 6 7 8 9 10 hi,there 1 2 3 see example16

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

71 71 for $i in expr1 order by expr2 return expr3 { for $i in //Member order by $i/Name/text() ascending return {$i/Name/text()} } 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 72 Sort the Numbers <= 20 Output: 0 1 2 5 8 13 14 15 17 19 0 8 23 17 5 19 44 13 78 21 2 1 15 67 99 14 8 33 50 Numbers.xml Numbers.xq see example18 { for $i in //Number[number(text()) {$i/text()} }

73 73 for $i in expr1 where expr2 order by expr3 return expr4 { for $i in //Number where number($i) {$i/text()} } 0 8 23 17 5 19 44 13 78 21 2 1 15 67 99 14 8 33 50 Numbers.xml Numbers_v2.xq see example18 Here's an alternative (equivalent) solution using "where expr": Output: 0 1 2 5 8 13 14 15 17 19

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

75 75 Jeff David Roger Stacey Linda John Diane Andy Josh Donna 19 22 25 29 32 35 39 40 44 50 This data is sorted by id value This data is sorted by Age David39 Jeff35 Linda40 Roger32 Stacey25 This data is sorted by Name Just interested in the first 5 Members (i.e., @id <= 5) Join each Member's Name with their Age

76 76 { 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 {$i/Name/text()} {$j/text()} } Jeff David …... 35 39... $i $j see example19 MemberInfo.xq MemberAges.xml MemberNames.xml

77 77 for $i in expr1 let $j := expr2 where expr3 order by expr4 return expr5 { 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 {$i/Name/text()} {$j/text()} } Jeff David …... 35 39... $i $j see example19 MemberInfo_v2.xq This is an alternate (equivalent) solution

78 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 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 80 let $j := expr The let clause is not a looping mechanism. It is only a variable assignment mechanism. $i $j $k { for $i in (1 to 3) let $j := ("red", "white", "blue") for $k in (4 to 6) return {$i} {$j} {$k} } $i$j$k 1 red white blue4 1 red white blue5 1 red white blue6 2 red white blue4 2 red white blue5 2 red white blue6 3 red white blue4 3 red white blue5 3 red white blue6 Output: see example20 Do Lab4

81 81 Create a list of the names of all the elements in the XML { let $i := for $j in //* return name($j) for $k in $i return {$k} } Output: FitnessCenter Member Name Member Name see example20-a

82 82 Create a list of distinct FavoriteColor values { let $source := doc("FitnessCenter.xml") let $colors := $source//FavoriteColor let $distinct := distinct-values($colors) for $i in $distinct return {$i} } Output: lightgrey lightblue lightyellow purple see example20-b

83 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 84 Show the members for each favorite color { let $source := doc("FitnessCenter.xml") let $colors := $source//FavoriteColor let $distinct := distinct-values($colors) for $i in $distinct return Members with {$i} as their favorite color: { let $names := $source//Member[child::FavoriteColor eq $i]/Name for $j in $names return {data($j)} } } see example20-c

85 85 Alternate solution, using "where" { let $source := doc("FitnessCenter.xml") let $colors := $source//FavoriteColor let $distinct := distinct-values($colors) for $i in $distinct return Members with {$i} as their favorite color: { for $j in $source//Member where $j/child::FavoriteColor eq $i return {$j/data(Name)} } } see example20-d

86 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; Name Old Rate New Rate { for $i in //Member return {$i/Name/text()} {if ($i/@level eq "platinum") then 500 else if ($i/@level eq "gold") then 450 else 400} {if ($i/@level eq "platinum") then 500 * $increase else if ($i/@level eq "gold") then 450 * $increase else 400 * $increase} } see example21

87 87 Jeff David Roger Stacey Linda John declare variable $increase := 1.1; Name Old Rate New Rate { for $i in //Member return {$i/Name/text()} {if ($i/@level eq "platinum") then 500 else if ($i/@level eq "gold") then 450 else 400} {if ($i/@level eq "platinum") then 500 * $increase else if ($i/@level eq "gold") then 450 * $increase else 400 * $increase} } FitnessCenter.xml FitnessCenter.xq NameOld RateNew Rate Jeff500550 David450495 Roger500550 Stacey400440 Linda450495 John500550 see example21

88 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 function name (params) as type { expr }; … declare namespace prefix = "URI";... … Variable Declarations Function Declarations Body Prolog Namespace Declarations Version Declaration

89 89 xquery version="1.0" encoding="UTF-8"; declare variable $var := expr;... declare function name (params) as type { expr }; … declare namespace prefix = "URI";... … Use Semicolons in Prolog

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

91 91 Using functions declare namespace ex = "http://www.example.org"; declare variable $multiplicand := 3; declare function ex:multiply ($num) { $num * $multiplicand }; Old Value New Value { for $i in //Number return {data($i)} {ex:multiply($i)} } namespace declaration variable declaration function declaration see example23

92 92 declare namespace ex = "http://www.example.org"; declare variable $multiplicand := 3; declare function ex:multiply ($num) { $num * $multiplicand }; Old Value New Value { for $i in //Number return {data($i)} {ex:multiply($i)} } 0 8 23 17 5 19 44 13 78 21 2 1 15 67 99 14 8 33 50 Numbers.xml Numbers.xq see example23

93 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 94 Don't forget the semicolons declare namespace ex = "http://www.example.org"; declare variable $multiplicand := 3; declare function ex:multiply ($num) { $num * $multiplicand }; Old Value New Value { for $i in //Number return {data($i)} {ex:multiply($i)} }

95 95 If you do forget... declare namespace ex = "http://www.example.org"; declare variable $multiplicand := 3; declare function ex:multiply ($num) { $num * $multiplicand }... Error XQuery syntax error on line 10 of Numbers.xq in '... $num * $multiplicand } <': expected ";", found " " forgot the semicolon here Here's the error message you will get:

96 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

97 97 Identity transform plus lcase Write an XQuery function. Pass it XML. It converts all the element and attribute names to lower case. Jeff lightgrey David lightblue Roger lightyellow Jeff lightgrey David lightblue Roger lightyellow

98 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 99 Oops! Forgot the attributes The function lost the attributes. The next slide shows an XQuery function that doesn't loose the attributes.

100 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 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"; Old Value New Value { for $i in //Number return {data($i)} {m:multiply($i)} } Numbers.xq see example24

102 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's targetNamespace Namespace prefix

103 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 104 import the module import module namespace m = "http://www.multiplication.org" at "Multiplication-Module.xqm"; Old Value New Value { for $i in //Number return {data($i)} {m:multiply($i)} } URL location of the module Identify the namespace of the module

105 105 Namespaces must match module 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"; Old Value New Value { for $i in //Number return {data($i)} {m:multiply($i)} } The prefixes don't have to match

106 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 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"; Old Value * Value + Value { for $i in //Number return {data($i)} {m:multiply($i)} {a:add($i)} } 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

108 108 Single Module, Multiple Functions import module namespace m = "http://www.math.org" at "Math-Module.xqm"; Old Value * Value + Value { for $i in //Number return {data($i)} {m:multiply($i)} {m:add($i)} } Numbers.xq see 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 contain only one module.

109 109 Type Checking import module namespace m = "http://www.math.org" at "Math-Module.xqm"; declare namespace xsd = "http://www.w3.org/2001/XMLSchema"; Old Value * Value + Value { for $i in //Number return {xsd:integer($i)} {xsd:integer(m:multiply($i))} {xsd:integer(m:add($i))} } see example27 By wrapping a value within a datatype you are instructing the XQuery processor to validate that the value is of that data type.

110 110 Type checking against user-defined types import schema namespace bk = "http://www.books.org" at "UserDefinedSimpleTypes.xsd"; Chapter { for $i in //li return {bk:Chapter($i)} } CheckChapterList.xq Chapter1 Chapter2 Chapter3 Chapter4 Chapter5 Chapter6 Chapter7 Chapter8 Chapter9 ChapterList.xml <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.books.org" xmlns="http://www.books.org" elementFormDefault="qualified"> UserDefinedSimpleTypes.xsd see example28

111 111 import XML Schema URL location of the XML Schema Identify the targetNamespace of the XML Schema import schema namespace bk = "http://www.books.org" at "UserDefinedSimpleTypes.xsd"; Chapter { for $i in //li return {bk:Chapter($i)} }

112 112 Type checking against user-defined types that are in no namespace import schema default element namespace "" at "UserDefinedSimpleTypes.xsd"; Chapter { for $i in //li return {$i cast as Chapter} } CheckChapterList.xq Chapter1 Chapter2 Chapter3 Chapter4 Chapter5 Chapter6 Chapter7 Chapter8 Chapter9 ChapterList.xml <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> UserDefinedSimpleTypes.xsd see example29 Do this

113 113 $var cast as datatype import schema default element namespace "" at "UserDefinedSimpleTypes.xsd"; Chapter { for $i in //li return {$i cast as Chapter} } Import an XML Schema where the elements and types are in no namespace Type cast the value of $i to the user-defined type Chapter.

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

115 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 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 The Origin of Wealth Eric D. Beinhocker 2006 1-57851-777-X Harvard Business School Press 29.95 … XML Text

117 117 let $source := doc("bookstore.xml") return ( string($source/bookstore/@storename), for $i in $source//book return ( " ", (: 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 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., 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/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 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 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 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 ( " ", 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

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

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


Download ppt "1 Roger L. Costello 16 June 2010 XQuery"

Similar presentations


Ads by Google