XQUERY
Tiziana Mancinelli
XQUERY
Learn XQuery: A list of great articles, blog posts, and books for learning XQuery
Resources
- XML Query Language (http://www.w3.org/TR/xquery/)
- Xquery is a programming language
- is a functional language (
- used for XML documents and XML databases
- It uses XPATH
- useful for extraction and selection of XML fragments and construction of new elements
What is XQuery?
Tools to use Xquery
- Databases - BaseX - ExistDB
- Xquilla (riga di comando)
- A few libraries to embed Xquery
- oXygen
XQuery defines the FLWOR iteration syntax.
FLWOR is the acronym for for, let, where, order by, and return.
A FLWOR statement is made up of the following parts:
What is XQuery?
A FLWOR statement is made up of the following parts:
What is XQuery?
-
One or more FOR clauses that bind one or more iterator variables to input sequences.
-
An optional where clause. This clause applies a filter predicate on the iteration.
-
An optional order by clause.
-
An optional let clause. This clause assigns a value to the given variable for a specific iteration. The assigned expression can be an XQuery expression such as an XPath expression, and can return either a sequence of nodes or a sequence of atomic values.
-
A return expression. The expression in the return clause constructs the result of the FLWOR statement.
A FLWOR statement is made up of the following parts:
What is XQuery?
-
where: filter a sequence (optional) → never use with eXist-db!
Let's remember the
Namespace (!)
declare namespace tei=”http://www.tei-c.org/ns/1.0";
XQUERY
Let's decrypt this script
doc > is a native function for Xquery, passing it the name of the resource to open --> ("../data/example.xml")
Within eXist-db will open resources known by eXist
xquery version "3.1";
declare namespace tei="http://www.tei-c.org/ns/1.0";
let $titles := doc("../data/esempio.xml")//tei:title
return $titles
LET > is used to set the value a variable through :=
let $titles := doc("../example.xml")//tei:author
return count($titles)
What is a variable?
a variable is bound to a particular value. That value may be any sequence, including a single node or multiple nodes. They are precedeending by a dollar
XQUERY
let $titles := doc("../data/example.xml")//tei:title
return count($titles)
l
every time a let is set, you need than a return (!)
let $titles := doc("../data/example.xml")//tei:title
return count($titles)
Execute the count function giving the variable called $titles
XQUERY
XQUERY
for $title in doc("../data/example.xml")//tei:title
return $title
Let's have another example with 'for'
XQUERY
In order to return the content of a node, use:
let $namevariable := doc(example.xml)/elementXML
return $navariable/data()
XQUERY
Building New HTML or XML with XQuery: Using Curly Braces: { }
To add HTML or XML markup to the XQuery output, add the elements where needed to produce conformant code. However, these elements are passive, or non-functional when executing XQuery commands. So we use curly-braces { } to enclose any XPath or XQuery statements that we want to execute in XQuery, to separate them from the HTML or XML markup elements. Inside html elements, when we need to do some calculation or refer to a variable we defined in XQuery, we use the curly-braces again.
Title Text
XQUERY
xquery version "3.0";
declare namespace tei="http://www.tei-c.org/ns/1.0";
for $title in doc("../data/example.xml")//tei:title
return <p>{$title/data()}</p>
An example with order by
XQUERY
xquery version "3.0";
declare namespace tei="http://www.tei-c.org/ns/1.0";
for $title in doc("../data/example.xml")//tei:title
order by string-length($title/data())
return <p>{$title/data()}</p>
Text
XQUERY
for $title in doc("../data/lettera_2.xml")//tei:title
where contains($title, ' ')
order by string-length($title/data())
return <p>{$title/data()}</p>
An example with where
e/data()}</i>
XQUERY
xquery version "3.1";
declare namespace tei="http://www.tei-c.org/ns/1.0";
for $title in doc("example.xml")//tei:title
return if ($title/../name() = "titleStmt")
then <strong>{$title/data()}</strong>
else <i>{$title/data()}</i>
Let's have a condition! (: let's have fun! :)
Title Text
XQUERY
xquery version "3.1";
declare namespace tei="http://www.tei-c.org/ns/1.0";
for $title in doc("example.xml")//tei:title
return if ($title/ancestor::tei:titleStmt) place="marginleft"
then <strong>{$add/data()}</strong>
else <em>{$title/data()}</em>
Functions
Built-in Versus User-Definend Functions
- Function within Xquery
- You can create function with Xquery
XQUERY
- Built-in Versus User-Definend Functions
- Function within Xquery
- All the Xpath functions can be used in Xquery as well
XQUERY
Built-in Versus User-Definend Functions
Function within Xquery
such as -- concat
xquery version "3.1";
declare namespace tei="http://www.tei-c.org/ns/1.0";
let $title := doc("../data/lettera_2.xml")//tei:titleStmt
return concat($title/tei:respStmt/tei:name/data(), ", ", " ", $title/tei:title)
XQUERY
(: Functions :)
declare function prefix:function_name($parameter as datatype) as returnDatatype
{
...function code here...
};
Parameters needs to be followed by a comma!
Function
declare namespace tei="http://www.tei-c.org/ns/1.0";
declare function local:countHands($node as node()) {
count($node//*[@hand])
};
let $root := doc("Frankenstein-v1c5-transcription.xml")
return <html>
<body>
<p>Corrections: {local:countHands($root)}</p>
</body>
</html>
XQUERY
Return datatype
declare function local:getTitle () as xs:string
www.w3.org/2001/XMLSchema
L'XML-SCHEMA of the many things it does, define typologies of data.
XQUERY
Return datatype
declare function local:getTitle () as xs:integer {
42
};
declare function local:getTitle () as xs:string {
42
};
https://www.w3.org/TR/xmlschema-2/
XQUERY
Return datatype
declare function local:getTitle () as xs:string {
string-join(doc("example.xml")//tei:titleStmt/tei:title, "-")
};
XQUERY
$parameter as datatype
declare function local:getTitle($resource as xs:string) as xs:string {
string-join(doc($resource)//tei:titleStmt/tei:title, "-")
};
let $title := local:getTitle("../data/lettera_2.xml")
return $title
XQUERY
$parameter as datatype
let $title := local:getTitle("../data/lettera_2.xml")
let $title2 := local:getTitle("../data/lettera_3.xml")
return <p>{$title, $title2}</p>
L'XML nelle tante cose che fa, definisce anche i tipi di dato.
https://www.w3.org/TR/xmlschema-2/
XQUERY
Function
Built-in Versus User-Definend Functions
- Use the declare function keyword
- The name of the function must be prefixed
- The data type of the parameters are mostly the same as the data types defined in XML Schema
- The body of the function must be surrounded by curly braces
XQUERY
Functions in the template always have two parameters
the first is ($node as node(),
node is the XML element with data-template attribute which trigger the execution of the function
XQUERY
Functions in the template always have two parameters
the first is ($node as node(),
node is the XML element with data-template attribute which trigger the execution of the function
and the second $model as map(*))
XQUERY
let $root := doc("Frankenstein-v1c5-transcription.xml")
return <html>
<head>
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"/>
<meta
charset="UTF-8"/>
</head>
<body><div
class="container">
<div
class="row">
<div
class="col-sm">
{
let $graphicUrl := $root//tei:facsimile/tei:graphic/@url
return
<img
width="600"
src="{$graphicUrl}"/>
}
</div>
<div
Corrections: {local:countHands($root)}
</div>
</div>
</div>
</body>
</html>
declare function local:applyTemplates($nodes as node()*) as node()* {
for $node in $nodes
return
typeswitch ($node)
case element(tei:head)
return
local:applyTemplateHead($node)
case element(tei:p)
return local:applyTemplateP($node)
case element()
return local:applyTemplates($node/node())
default
return $node
}
Typeswitch
Typeswitch
The most effective way to use the typeswitch expression to transform XML is to create a series of XQuery functions. In this way, we can cleanly separate the major actions of the transformation into modular functions. (In fact, the library of functions can be saved into an XQuery library module, which can then be reused by other XQueries.) The "magic" of this typeswitch-style transformation is that once you understand the basic pattern and structure of the functions, you can adapt them to your own data. You'll find that the structure is so modular and straightforward that it's even possible to teach others the basics of the pattern in a short period of time and empower them to maintain and update the transformation rules themselves.
declare function local:applyTemplateHead($node as node()) as node()* {
<h1>{local:applyTemplates($node/node())}</h1>
};
declare function local:applyTemplateP($node as node()) as node()* {
<p>{local:applyTemplates($node/node())}</p>
};
<html>
<head>
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"/>
<meta
charset="UTF-8"/>
</head>
<body><div
class="container">
<div
class="row">
<div
class="col-sm">
{
let $graphicUrl := $root//tei:facsimile/tei:graphic/@url
return
<img
width="600"
src="{$graphicUrl}"/>
}
</div>
<div
class="col-sm"
style="margin-left: 5em">
{
let $teiHead := $root//tei:head
return local:applyTemplates($teiHead)
}
{
let $teiP := $root//tei:div//tei:p
return local:applyTemplates($teiP)
}
Corrections: {local:countHands($root)}
</div>
</div>
</div>
</body>
</html>
declare function app:title($node as node(), $model as map(*)) {
<h1>{string-join(doc("../data/lettera_2.xml")//tei:titleStmt/tei:title, "-")}</h1>
};
XQUERY
Body
declare function app:body($node as node(), $model as map(*)) {
<p>{doc("../data/lettera_2.xml")//tei:body }</p>
};
XQUERY
---> index.html
<div data-template="app:body" />
XQUERY
---> index.html
Why is not imported the module?
XQUERY
Because it is processed in the template system. The template system runs because we have view.xql- (which is not a module)
view.xql >> import app.xlq
To create an element
declare function app:body($node as node(), $model as map(*)) {
element p {
doc("../data/lettera_2.xml")//tei:body
}
};
XQUERY
Body
declare function app:body($node as node(), $model as map(*)) {
element p {
attribute style { "border: 1px solid red" },
doc("../data/lettera_2.xml")//tei:body
}
};
XQUERY
Body
declare function app:body($node as node(), $model as map(*)) {
let $id := request:get-parameter("id", ())
let $object := collection("apps/example/data")/tei:TEI[@xml:id = $id]
return
element p {
$object//tei:body
}
};
XQUERY
Xquery - Bologna2021
By Tiziana Mancinelli
Xquery - Bologna2021
University of Bologna - Xquery
- 586