{ }
.FOR $item in $list
⮕ beginnt einen for-each
-loopLET $id := $item/@id
⮕ belegt Variablen
(Variablennamen starten mit $
, Werte werden mit dem "Walrossoperator" :=
zugewiesen)WHERE $id > 100
⮕ schränkt durch konditionale Abfragen einORDER / SORT / GROUP BY $item/@sortkey
⮕ permutiert die ErgebnislisteRETURN $item/data()
⮕ gibt die Ergebnismenge zurückunparsed-text()
eingelesen werden.declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare variable $Sturm_Persons := doc("Sturm_persList.xml");
xml
, xhtml
, html
, text
, json
, adaptive
):
declare namespace output="http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:method "html";
xquery version "3.0";
declare 6 namespace tei = "http://www.tei-c.org/ns/1.0";
declare variable $Sturm_Persons := 7 doc("Sturm_persList.xml");
<ul>1
{
for $person in $Sturm_Persons//tei:person
return 2<li>3{$person/4tei:persName/data()5}</li>
}
</ul>
Gibt zurück:
<ul>1
2<li>3Alma</li>
<li>Arnold, Ernst (Galerie)</li>
<li>August (Stramm?)</li>
<li>Bechteev, Vladimir G.</li>
<li>Beckerath, Willy von</li>
<li>Beffie, Willem Wolff</li>
…
<li>Wiegand, Charmion von</li>
</ul>
4 Damit die Abfrage funktioniert müssen Tags, die im TEI-Namespace stehen gekennzeichnet werden. Das geschieht an dieser Stelle durch das Namespace-Präfix tei:
, an das im Prolog 6 die Namespace-URL gebunden worden war.
5/data()
gibt die Textknoten eines Elementknotens zurück.
7 Die XML-Datei, die verarbeitet werden soll, wird mit der XPath-Funktion doc()
eingelesen und in einer Variable verfügbar gehalten.
xquery version "3.0";
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare variable $Sturm_Persons := doc("Sturm_persList.xml");
<ul>
{
for $person in $Sturm_Persons//tei:person
return <li>
1<name>{$person/tei:persName/data()}</name>
2<id>{$person/@xml:id/data()}</id>
3<letter_count>{4count($person/tei:linkGrp/tei:ptr)}</letter_count>
</li>
}
</ul>
Gibt zurück:
<ul>
<li>
1<name>Alma</name>
2<id>P.0000032</id>
3<letter_count>2</letter_count>
</li>
<li>
<name>Arnold, Ernst (Galerie)</name>
<id>P.0000059</id>
<letter_count>3</letter_count>
</li>
…
</ul>
4 In einem XQuery-Skript können jederzeit XPath-Funktionen benutzt werden, hier bspw. count()
.
xquery version "3.0";
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare namespace output="http://www.w3.org/2010/xslt-xquery-serialization";
declare option output:method "html";
declare variable $Sturm_Persons := doc("Sturm_persList.xml");
<html lang="de">
<head>
<title>Sturm-Personen</title>
</head>
<body>
<h1>Personen</h1>
<ul>
{
for $person in $Sturm_Persons//tei:person
return <li>
<span
id="{$person/@xml:id/data()}"
2data-id="{$person/@xml:id/data()}"
2data-letter_count="{count($person/tei:linkGrp/tei:ptr)}">
{$person/tei:persName/data()}
(letters: {count($person/tei:linkGrp/tei:ptr)})
</span>
</li>
}
</ul>
</body>
1<script type="text/javascript" src="script.js"></script>
</html>
1 In einem XQuery-Output können jederzeit alle Bereiche einer Ausgabedatei, bspw. einer HTML-Datei, generiert werden. Es gibt aber auch Frameworks, die Template- und Partial-basierte Ansätze im Kontext XQuery erlauben, um Ausgaben zu modularisieren. 2 Das im Beispiel eingebundene javascript-Skript greift auf die im HTML "versteckten" data
-Attribute zu, um spezifische interaktive Funktionalität bereitzustellen.
xquery version "3.0";
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare variable $Sturm_Persons := doc("Sturm_persList.xml");
<ul>
{
for $person in $Sturm_Persons//tei:person
1where 2 some $ptr in $person//tei:ptr
3satisfies (4contains(lower-case($ptr/@target), 'jvh'))
return <li>{$person/tei:persName/data()}</li>
}
</ul>
Gibt zurück:
<ul>
<li>Alma</li>
<li>Beffie, Willem Wolff</li>
<li>Behne, Adolf</li>
<li>Bremmer, Henk</li>
<li>Breuer, Robert</li>
…
</ul>
1 In Anlehnung an SQL können Ergebnismengen mit where
eingeschränkt werden. Das allgemeine where
kann daraufhin mit Vergleichs-Operatoren (=, <, >, !, not()
) oder einer 2 3 Kombination von Schlüsselwörtern (some, satisfies
) in Kombination mit 4 einer einen Wahrheitswert zurückgebenden XPath-Funktion (contains()
) weiter eingeschränkt werden.
xquery version "3.0";
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare variable $Sturm_Persons := doc("Sturm_persList.xml");
<ul>
{
for $person in $Sturm_Persons//tei:person
1where 2 every $ptr in $person//tei:ptr
3satisfies (4contains(lower-case($ptr/@target), 'jvh'))
return <li>{$person/tei:persName/data()}</li>
}
</ul>
Gibt zurück:
<ul>
<li>Alma</li>
<li>Bremmer, Henk</li>
<li>Breuer, Robert</li>
<li>Bruder (von Francisca van Leer)</li>
<li>Bruggen Cate, J.D. ten</li>
…
</ul>
1 In Anlehnung an SQL können Ergebnismengen mit where
eingeschränkt werden. Das allgemeine where
kann daraufhin mit Vergleichs-Operatoren (=, <, >, !, not()
) oder einer 2 3 Kombination von Schlüsselwörtern (every, satisfies
) in Kombination mit 4 einer einen Wahrheitswert zurückgebenden XPath-Funktion (contains()
) weiter eingeschränkt werden.
xquery version "3.0";
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare variable $Sturm_Persons := doc("Sturm_persList.xml");
<ul>
{
for $person in $Sturm_Persons//tei:person
return 1 if ($person/@source) 2 then <li>{$person/tei:persName/data()} (<a href="{$person/@source/data()}">GND</a>)</li>
3else <li>{$person/tei:persName/data()} (no GND)</li>
}
</ul>
Gibt zurück:
<ul>
<li>Alma (no GND)</li>
<li>Arnold, Ernst (Galerie) (<a href="http://d-nb.info/gnd/2097840-6">GND</a>)</li>
<li>August (Stramm?) (no GND)</li>
<li>Bechteev, Vladimir G. (<a href="http://d-nb.info/gnd/13236056X">GND</a>)</li>
<li>Beckerath, Willy von (<a href="http://d-nb.info/gnd/118888692">GND</a>)</li>
…
</ul>
Konditionale, entscheidende Konstruktionen nach dem Schema if/else
sind auch aus anderen Programmierkontexten bekannt. In Xquery muss einem 1 Test mit if
explizit mit 2 then
Code zugewiesen werden, der auszuführen ist, wenn die Abfrage true
(wahr) zurückgibt. Alternativen können mit 3
else
notiert werden. if/then/else
-Konstrukte lassen sich verschachteln.
xquery version "3.0";
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare namespace g = "https://d-nb.info/standards/elementset/gnd#";
declare namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
declare namespace rdfs = "http://www.w3.org/2000/01/rdf-schema#";
declare 1 namespace local = "http://fake.url";
declare variable $Sturm_Persons := doc("Sturm_persList.xml");
declare 2 function local:3getGender(4$url 5 as xs:string)
6as xs:string? 7 {
let $res := doc($url)//g:gender
8return if ($res) then ( $res//rdfs:label/data() )
else ('Unbekannt')
};
<ul>
{ for $person in $Sturm_Persons//tei:person
return if ($person/@source and contains($person/@source, 'gnd'))
then <li>{$person/tei:persName/data()}
({9local:getGender(concat('https://lobid.org/gnd/',substring-after($person/@source, '/gnd/'), '.rdf'))})</li>
else <li>{$person/tei:persName/data()} (no GND)</li> }
</ul>
Gibt zurück:
<ul>
<li>Alma (no GND)</li>
<li>Arnold, Ernst (Galerie) (Unbekannt)</li>
<li>August (Stramm?) (no GND)</li>
<li>Bechteev, Vladimir G. (Unbekannt)</li>
<li>Beckerath, Willy von (Männlich)</li>
…
<li>Werefkin, Marianne von (Weiblich)</li>
…
</ul>
1 Im Prolog wird ein eigener Namespace für die zu schreibenden Funktionen deklariert und an ein Präfix gebunden. 2 mit dem Schlüsselwort function
wird eine Funktion deklariert und 3 benannt (NS-Präfix nicht vergessen!). Es werden 4 Parameter (Argumente) und ihr 5 Datentyp angegeben. Ebenfalls wird der 6 Datentyp des Rückgabe-Wertes angegeben. Es folgt 7 der eigentliche Funktionskörper, also die eigentliche Verarbeitung. Mit dem 8 Schlüsselwort return
wird eine Rückgabe notiert. 9 Aufgerufen wird wie eine normale XPath-Funktion (NS-Präfix nicht vergessen!).
xquery version "3.0";
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare namespace g = "https://d-nb.info/standards/elementset/gnd#";
declare namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
declare namespace rdfs = "http://www.w3.org/2000/01/rdf-schema#";
declare namespace local = "http://fake.url";
declare variable $Sturm_Persons := doc("Sturm_persList.xml");
declare function local:getGender($url)
as xs:string? {
let $res := doc($url)//g:gender
return if ($res) then (
1switch(2$res//rdfs:label/data())
3case 'Männlich' return '♂'
4case 'Weiblich' return '♀'
5default return '?'
) else ('??')
};
<ul>
{ for $person in $Sturm_Persons//tei:person
return if ($person/@source and contains($person/@source, 'gnd'))
then <li>{$person/tei:persName/data()}
({local:getGender(concat('https://lobid.org/gnd/',substring-after($person/@source, '/gnd/'), '.rdf'))})</li>
else <li>{$person/tei:persName/data()} (no GND)</li> }
</ul>
Gibt zurück:
<ul>
…
<li>Walden, Herwarth (♂)</li>
<li>Walden, Nell (♀)</li>
<li>Werefkin, Marianne von (♀)</li>
<li>Wichert (no GND)</li>
<li>Wiegand, Charmion von (?)</li>
</ul>
Eine switch/case
-Konstruktion liest innerhalb des Schlüsselwortes 1 switch()
einen 2 Text- oder Attributwert-Knoten ein. Dessen Wert (String) wird dann auf die mit 3 4 case
angegebenen Fälle getestet (hier: Männlich, Weiblich
), ist der Test true
(wahr) wird der folgende Code ausgeführt. Es kann ein 5 default
definiert werden, d.h. ein Fall der immer dann gilt, wenn alle vorherigen nicht gegolten haben.
xquery version "3.0";
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare variable $Sturm_Persons := doc("Sturm_persList.xml");
<ul>
{
for $person in $Sturm_Persons//tei:person
return 1 element 2 li
{7
3 attribute 4 id 5 {$person/@xml:id},
6 $person/tei:persName/data()
}
}
</ul>
Gibt zurück:
<ul>
1<2li 34 id="P.0000032" 5>6Alma</li>
<li id="P.0000059">Arnold, Ernst (Galerie)</li>
<li id="P.0000083">August (Stramm?)</li>
<li id="P.0000063">Bechteev, Vladimir G.</li>
<li id="P.0000072">Beckerath, Willy von</li>
…
</ul>
Elemente und Attribute können mit den Schlüsselwörtern 1 element
oder 3 attribute
an Ort und Stelle konstruiert werden. Direkt im Anschluss an die Schlüsselwörter folgen die gewünschten 2 Element- bzw. 4 Attribut-Namen. 56 Die gewünschten Inhalte folgen in geschweiften Klammern {}
. Attribut-Konstruktoren werden also 7 "innerhalb" des Inhalts eines Elementkonstruktors notiert (wenn ein solcher existiert).
# Headline
I’am a paragraph.
## Second Order Headline
I am a paragraph as well.
Query:
xquery version "3.0";
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare 2 variable $raw := 1 unparsed-text("rawtext.md");
<document>
{ 5 for $line in 4 tokenize($raw, 3' ')
6return 7 if (starts-with($line, '#'))
then 8 element { concat('h',
string-length(
substring-before($line, ' ')
)) }
{ substring-after($line, ' ') }
7else if (normalize-space($line) != '') then 8 <p>{$line}</p>
7else '' }
</document>
Gibt zurück:
<document>
<h1>Headline</h1>
<p>I’am a paragraph.</p>
<h2>Second Order Headline</h2>
<p>I am a paragraph as well.</p>
</document>
Der Markdown-Text wird per 1 unparsed-text()
in 2 eine Variable ($raw
) eingelesen. Daraufhin wird der Text der Datei an 3 Zeilenumbrüchen per 4 tokenize()
in eine Liste (array
) von Zeilen zerteilt, über die in einer 5 Schleife iteriert werden kann. Innerhalb des 6 return
-Statements werden 7 Tests durchgeführt, die den Typ der aktuellen zeile bestimmen sollen (Überschrift, normaler Text, …). 8 Jenachdem wird spezifisches Markup um die Zeile herum geschrieben.