Das XQuery-Datenmodell

Werbung
Das XQuery-Datenmodell
Gliederung
•
•
•
•
•
•
•
•
Sequenzen
Atomare Werte
Knoten
Knoteneigenschaften
Sequenztypen und Knotenzugriffsfunktion
Typabfrage
Gleichheit von Sequenzen
Zusammenfassung
Das XQuery-Datenmodell
• Das Datenmodell ist eine interne
Darstellung eines XML Dokumentes.
Zentraler Konstrukt ist eine Sequenz mit
einer beliebigen Anzahl von Einträgen
(atomare Werte oder Knoten), die eine
Position haben.
Struktur einer Sequenz
• Eine Sequenz besteht aus keinem, einem oder
mehreren Einträgen („items“) atomarer Wert oder
Knoten
• Die einzelnen Einträge werden aneinander gereiht durch
Komma getrennt.
• Eine Klammerung ist oft nicht notwendig verdeutlicht
aber die Sequenzbildung
• Eine leere Sequenz wird durch () dargestellt, sie ist aber
von „Nichts“ zu unterscheiden
• Auch ein einzelner Wert ist eine Sequenz
• Sequenzen können nicht ineinander verschachtelt sein
• Eine Sequenz ist geordnet und hat keine
Mengeneigenschaften Duplikate
Beispiele identischer Sequenzen
• (1,2,1) und (1,(2,1)) liefert eine Sequenz
aus drei Zahlen
• (1, (),<B/>) und (1, <B/>) liefert eine
Sequenz aus Zahl und Knoten
• (<A/>) und <A/> liefert eine Sequenz mit
nur einem Eintrag
• () und ( (), () ) liefert die leere Sequenz
Funktionen und Operationen auf
Sequenzen
• Da jeder Ausdruck in XQuery eine Sequenz ergibt, sind
alle Funktionen in XQuery Funktionen auf Sequenzen
• Man unterscheidet 2 Gruppen, die sich mit der Struktur
von Sequenzen befassen:
Kardinalität von Sequenzen und Veränderung von
Sequenzen
- Bei der Syntaxdarstellung werden die Parameter, die
Sequenzen darstellen, mit $seq benannt
- Die Notation item()* steht für einen allgemeinen
Sequenztyp
Kardinalität von Sequenzen
Signatur
Beschreibung
fn:zero-or-one
($seq as item() *)
as item() ?
Eingabesequenz
höchstens einen
Eintrag, sonst Fehler
fn:one-or-more
($seq as item() *)
as item() +
Eingabesequenz
mindestens einen
Eintrag, sonst Fehler
fn:exactly-one
($seq as item() *)
as item()
Eingabesequenz
genau einen Eintrag,
sonst Fehler
fn:empty
($arg as item() *)
as xs:boolean
True
Eingabesequenz leer,
sonst false
fn:exists
($arg as item() *)
as xs:boolean
True
Eingabesequenz nicht
leer, sonst Fehler
fn:count
($seq as item() *)
as xs:integer
Anzahl der Einträge
einer Sequenz
Veränderung von Sequenzen
• Mit diesem Operator kann man auch einzelne Einträge
an eine Sequenz anfügen: let $seq := (1,2,3) return
($seq,4)  liefert (1,2,3,4)
• Mit der Funktion fn:insert-before() kann man auch an
andere Stellen der Sequenz Einträge einfügen. Das
Löschen von Einträgen geht mit der Funktion
fn:remove()
• Die Reihenfolge der Einträge in einer Sequenz kann mit
fn:reverse() umgedreht werden
• Mit fn:subsequence() kann man einen Ausschnitt aus
einer Sequenz bilden, indem Startposition und Anzahl
der Elemente angegeben werden.
• Die Funktion fn:unordered() gibt den Verzicht auf eine
bestimmte Reihenfolge wieder
Beispiele
• let $seq := („E1“,“E2“,“E3“,“E4“,E5“)
return fn:insert-before (fn:remove ($seq, 3), 3, „Neu“)
Ergebnis:
(„E1“,“E2“,“Neu“,“E4“,“E5“)
- let $seq := (6,5,4,3,2,1,0)
return subsequence( ($seq, fn:reverse ($seq)),
fn:count ($seq) div 2,
fn:count ($seq))
Ergebnis:
(3,2,1,0,0,1,2)
Veränderungen von SequenzenFunktionen
Signatur
Beschreibung
fn:insert-before ($seq as item()*,
$position as xs:integer,$seqneu as
item()*) as item()*
Neue Sequenz Einträge werden aus
der Sequenz $seqneu an Position
$position in die Sequenz $seq
eingeschoben
fn:remove ($seq as item()*, $position
as xs:integer) as item()*
Neue Sequenz der Eintrag in $seq
wird an Position $position entfernt
fn:reverse ($seq as item()*) as item()*
Neue Sequenz mit allen Einträgen
aus $seq in umgekehrter Reihenfolge
fn:subsequence ($seq as item()*,
$start as xs:double[,$length as
xs:double] ) as item()*
Neue Sequenz beginnend mit dem
Eintrag an Position round ($start) in
$seq, Rest von $seq wenn $length
fehlt
fn:unordered ($seq as item()*) as item
()*
Sequenz enthält alle Einträge aus
$seq, Reihenfolge unbestimmt
Atomare Werte
• Atomare Werte sind Instanzen eines
einfachen Typs bzw. von XML Schema,
z.B. Zeichenketten wie „Emma Müller“
oder Zahlen, z.B. 1.0.
• Werte von den Typen durch Vereinigung
oder Listenbildung sind keine atomaren
Werte.
Konstruktoren
• Konstruktoren sind dafür da, in einem
XQuery-Ausdruck einen Wert eines
bestimmten Typs anzugeben, z.B. als
Vergleichswert.
• xs:float (1) bezeichnet einen Wert des
Datentyps xs:float.
Literale für Zeichenketten
• Zeichenketten, die in einfache oder
doppelte Anführungszeichen stehen,
gelten als Werte vom Typ xs:string, z.B.:
`Dies ist ein Literal vom Typ xs:string`
„Solche Literale sind in““ oder `eingeschlossen“
• Die Anführungszeichen kann man auch im
Literal selbst verwenden, wenn man sie
verdoppelt.
Operationen und Funktionen auf
Sequenzen atomarer Werte
• Eine Sequenz aus Werten vom Typ xs:integer kann mit
dem to-Operator erzeugt werden: 3 to 7 die Sequenz
(3,4,5,6,7)
• Die Funktion fn:index-of() kann die Positionen innerhalb
der Sequenz liefern, an denen ein atomarer Wert steht,
der gleich dem Suchausdruck ist. Wird der Ausdruck
nicht gefunden, so ergibt sich eine leere Sequenz. Der
erste Eintrag einer Sequenz steht auf 1 nicht auf 0! Z.B:
fn:index-of( (1,0,0,1), 1) (1,4)
• Die Funktion fn:distinct-values() eliminiert Duplikate in
Sequenzen. Das Ergebnis enthält alle verschiedene
Werte, wobei die Reihenfolge abhängig ist von der
XQuery-Implementierung.
Funktionen auf Sequenzeinträgen
Signatur
Beschreibung
Op:to ($firstval as xs:integer,
Sequenz ganzzahliger Werte, die
$lastval as xs:integer) as xs:integer*
zwischen den beiden Werten der
Parameter liegen
fn:index-of
Liefert alle Positionen, an denen ein
Eintrag steht, der gleich dem
gesuchten Wert ist.
fn:distinct-values
Liefert alle verschiedenen Werte aus
der Eingabesequenz
Knoten
Elementknoten
• Ein Elementknoten repräsentiert ein Element aus XML
1.0.
• Der textuelle Wert eines Elementknotens ergibt sich aus
der Verkettung aller Textknoten, die diesem Knoten
folgen
• Wenn das Element keinen komplexen Inhalt hat (nicht
nur Kindelemente), hat das Element einen getypten
Wert.
• Beispiel: der getypte Wert hat den Typ xs:integer XML
Schema: einfacher Typ xs:integer! Hat das Element den
Typ xdt:untypedAny (unbest.komplexer Typ) ist der
getypte Wert vom Typ xdt:untypedAtomic
(unbest.atomarer Typ).
Erzeugung eines Elementknotens
• Der direkte Elementkonstruktor: benutzt die
vertraute XML-Notation, z.B. <Arzt
ID=„Arzt_01“>Hans Müller</Arzt>
• Referenzen auf vordefinierte Entitäten (z.B. <)
und Zeichenreferenzen (z.B.  ) in
Attributwerten und Elementinhalten sind erlaubt,
sie werden aber bei der Konstruktion aufgelöst:
<Fähigkeit>Altenbetreuung &
Altenpflege</Fähigkeit>
• Der berechnete Elementkonstruktor muss
eingesetzt werden, wenn auch der Name
eines Elementes berechnet werden soll
• „element“ „{„
Ausdruck_der_den_Namen_berechnet „}“
oder Ausdruck_der_den_Inhalt_berechnet
z.B.: element Labortest {
attribute ID {„Labortest_040782“},
element Nummer {1},
<Name>Röntgen</Name>
element Datum {„2002-05-10“},
}
Gemeinsame Regeln für beide
Konstruktorarten
• Das Präfix muss definiert sein, entweder
im XQuery-Prolog oder im Element selbst.
• Das Element wird automatisch gegen die
bekannten Schemadefinitionen validiert
und bekommt ggf. einen Typ zugewiesen.
Dokumentknoten
• Einen Dokumentknoten repräsentiert ein XMLDokument.
• Der textuelle Wert eines Dokumentknotens ergibt sich
aus der Verkettung der textuellen Werte aller
Textknoten, die dem DK folgen.
• Ein DK kann in XQuery mit einem berechneten
Konstruktor erzeugt werden, z.B. document {<Arzt>Emil
Müller</Arzt>}
• Die Knoten, die als Kinder dieses DKs angefügt werden,
verlieren jegliche Typinfo und ihnen werden die Typen
xs:anyType (Elementknoten) und xs:anySimpleType
(Attributknoten) zugewiesen.
Attributknoten
• Attributknoten entsprechen den Attributen
von XML- Elementen.
• Der textuelle Wert ergibt sich aus dem
Attributwert, gewandelt nach xs:string.
• Einen Attributknoten kann man über einen
berechneten Konstruktor erzeugen, bei
dem auf das Schlüsselwort „attribute“ der
Name des Attributs und sein Wert folgen,
z.B. attribute {$a} {6*7}
Kommentarknoten
• Ein Kommentarknoten entspricht einem
Kommentar in einem XML- Dokument.
• Der textuelle Wert besteht aus dem Inhalt
des Kommentars und dem getypten Wert
(Wert vom Typ xs:string).
• Direkter Konstruktor: <!- -Dies ist ein
Kommentar - ->
• Berechneter Konstruktor: comment {„Dies ist
ein Kommentar“}
Textknoten
• Ein Textknoten ist der einfache Inhalt
eines Elementes, unabhängig von seinem
Typ.
• Direkter Konstruktor: <![CData[Dies ist der
Inhalt des Textknotens]]>
• Berechneter Konstruktor: text {„Dies ist der
Inhalt des Textknotens“}
Knoteneigenschaften
Dokumentreihenfolge
• Die Dokumentordnung ist eine Ordnung der
Knoten in der Dokumentreihenfolge:
• Der Elternknoten wird vor seinen Kindern
besucht. Der Namensraumknoten eines
Elements werden vor den Attributknoten
desselben Elementes besucht. Die
Attributknoten werden vor den Kindern eines
Elementknotens besucht und die
Geschwisterknoten werden in der gleichen
Reihenfolge besucht wie im XML- Dokument
• Eliminierung identischer Knoten durch
Entfernung von Duplikaten
Funktionen auf Knoten
• Auf den Namen eines Knotens kann man mit
den XQuery- Funktionen fn:node-name() und
fn:name() zugreifen.
• Wenn der Knoten keinen Namen hat wird eine
leere Zeichenkette geliefert, sonst der Name
• Bei Attributen und Elementen kann der Name
aus einem Namensraum stammen
• fn:node-name()  Name als expandierten
QName kein Namensraumpräfix
• fn:name()  String in der syntaktischen Form
eines QName Namensraumpräfix gebraucht
• Oft sinnvoll auf den lokalen Namen und
der URI separat zuzugreifen: fn:local-name()
und fn:namespace-uri(), z.B. <A xmlns=
„http://x“/> local-name:A, namespaceuri:http://x
• Die in einem Knoten zugeordnete Wurzel des
Knotenbaumes wird mit der Funktion fn:root()
adressiert, z.B. fn:root (<Arzt/>)
• Textueller Wert eines Knotens fn:string
• Zugriff auf den getypten Wert mittels fn:data(),
z.B.: fn:string (<Name>
<Vorname>Daniela</Vorname>
<Nachname>Baumann</Nachname>
</Name>)
• fn:data(<Geburtstagsdatum>1982-0723</Geburtstagsdatum>)
• Zur Behandlung numerischer Daten
benutzt man fn:number(). Diese Funktion
erzeugt aus einem Knoten einen Wert des
Typs xs:double meldet einen Fehler,
wenn das Argument eine leere Sequenz
ist oder nicht von xs:double stammt.
• Z.B.: Es gilt: fn:number
(<A><B>1</B><C>2</C><A/>) =12.0 
fn:number
(<A><B>1.0</B><C>2.0</C></A>)
Sequenztypdefinitionen:
Häufigkeitsangaben
Symbol
Bedeutung
(keines)
Sequenz mit genau einem Eintrag
?
Sequenz mit höchstens einem Eintrag
+
Sequenz mit mindestens einem
Eintrag
empty()
Leere Sequenz
*
Sequenz mit unbeschränkter Anzahl
von Einträgen
Eintragstypen
• Der allgemeinste Eintragstyp item() lässt
sowohl atomare Werte als auch Knoten zu
• Als atomare Typen können alle in XML
Schema definierten einfachen Typen, wie
z.B.: xs:integer+ mein Namensraum:meine
Schuhgröße?  XQuery gibt nicht nur den
Typ an, sondern auch jeden davon mit
durch Erweiterung oder Restriktion
abgeleiteten Typ
Knotentypen
Knotentyp
Bedeutung
node()
document-node()
Beliebiger Knoten
Ein Dokumentknoten
document-node(element(…)) Ein Dokumentknoten, wobei
das Dokument als
Wurzelelement ein Element
hat
text()
Ein Textknoten
comment()
Ein Kommentarknoten
processing-instruction()
Ein
Verarbeitungsanweisungskn
processing-instruction(Ziel)
oten
Knotentyp
element(), element(*)
Ein beliebiger
Elementknoten
element(Name)
Ein bestimmtes Element
element(Name,Typ)
Ein Element mit bestimmtem
Namen und Typ
attribute(), attribute(*)
Ein beliebiges Attribut
attribute(Name)
ein bestimmtes Attribut
attribute(Name,Typ)
Ein Attribut mit bestimmtem
Namen und Typ
• Werden für ein Element Name und Typ angegeben,
werden alle Elemente akzeptiert, die diesen Namen
haben, z.B.: element (Angestellte, Angestellte_T)
• Der Typ des Elementes kann auch beliebig sein, z.B.:
element (Krankenwagenfahrer, *)
• Ein Element mit leerem Inhalt und dem Attribut
xsi:nil=„true“ wird nur akzeptiert, wenn das Schlüsselwort
nillable hinzugefügt wird: <Gehalt xsi:nil=„true“/>
element (*, xs:integer nillable)
• element (Krankenwagenfahrer)  führt zu einem Fehler,
da dieses Element nicht definiert wurde
• Element (Angestellte) akzeptiert ein Arzt- Element, da
er zu seiner Ersetzungsgruppe gehört
• XQuery erlaubt auch die Angabe eines Kontextpfades,
z.B. element (Operation/Beginn)
• Falls es eine Typdefinition ist: element
(type(Person_T)/E-Mail)
Operationen auf Sequenzen aus
Knoten
• Sequenzen von Knoten kann man
miteinander kombinieren, indem man den
Durchschnitt, die Vereinigung oder die
Differenz bildet
• Sequenzen werden hier temporär als
Menge betrachtet
• Die Ergebnisse der Sequenzoperationen
union, intersect und except sind immer
nach der Dokumentordnung sortiert.
Beispiel
• Let $doc := document {<Wurzel> 
ERGEBNIS:
<A>1</A> <A-Sequenz> <A>1</A> <A>3</A
<B>2</B>
></A-Sequenz>
<A>3</A> <B-Sequenz> <B>4</B> <B>2</B
<B>4</B>
></B-Sequenz>
</Wurzel>}
Let $a := $doc//A
Let $b := fn:reverse($doc//B)
Return
(<A-Sequenz>{$a}</A-Sequenz>,
<B-Sequenz>{$b}</B-Sequenz>,
<Vereinigung>{$a | $b}</Vereinigung>,
<Differenz>{$b excerpt $a}</Differenz>,
<Durchschnitt>{$b intersect $b}</Durchschnitt>)
Typabfrage
• XQuery stellt zur Abfrage des Typs eines
Sequenzwertes die Ausdrücke instance of und
typeswitch zur Verfügung.
• Instance of liefert den Wert true, wenn der Typ des
ersten Operanden mit dem zu überprüfenden Datentyp
übereinstimmt, z.B.: let $a :=xs:integer(4711)
where $a instance of xs:integer
and $a instance of xs:decimal
and $a instance of item()
return
<Text>Dieser Text wird erscheinen</Text>
• Die Typüberprüfung ist nicht nur für atomare Typen,
sondern für alle Sequenztypen möglich: <Text>bla
bla</Text> instance of element (*,xs:string)
• Ein typeswitch- Ausdruck entspricht der bekannten
switch- Anweisung, aber es entscheidet hier nicht der
Wert sondern der Typ des Auswahlausdrucks. Ein
typeswitch- Ausdruck besteht aus einer zu
überprüfenden Ausprägung eines Sequenztyps
(Angestellter für die Variable $a) und einer Liste von
Fällen, die zu überprüfen sind.
• Falls keine Typübereinstimmung erzielt werden kann,
wird der Ausdruck in der default-Klausel ausgewertet
und als Rückgabewert verwendet
• Hängt der Rückgabewert in einer case- oder defaultKlausel von der zu untersuchenden Sequenz ab, so
kann darauf zurückgegriffen werden, indem eine
zusätzliche Variable angegeben wird.
Beispiel
• typeswitch ($a)
case element (*, Arzt_T) return 25
case element (*, Pfleger_T) return 15
case element (*, Techniker_T) return 20
case element (*, Sekretärin_T) return 10
default return 0
 Überstunden in Abhängigkeit von der
Berufsgruppe. Überstunden werden bei Ärzten
mit 25, bei Pfleger nur mit 15 entlohnt. Die
Variable ist aus der Ersetzungsgruppe von
Angestellten.
Beispiel
• typeswitch ($a)
case $x as element (*, Arzt_T) return
<Merkmal> $x/Spezialgebiet</Merkmal>
Gleichheit von Sequenzen
• Es ist möglich zwei Sequenzen auf Gleichheit zu prüfen
mittels fn:deep-equal().
• Damit Sequenzen gleich sind müssen sie dieselbe
Anzahl von Einträgen haben und die Einträge müssen
an derselben Position jeder Sequenz paarweise gleich
sein.
• Eine leere Sequenz ist gleich einer leeren Sequenz
• Sind beide Einträge atomare Werte, ist die Gleichheit
über eq definiert Sortierordnung
• Ist ein Eintrag ein atomarer Wert und der andere ein
Knoten sind sie nicht gleich
• Sind beide ein Knoten ist die Gleichheit rekursiv definiert
• Die Art der Knoten muss gleich sein
• Wenn die Knoten Namen haben, müssen die Namen
gleich sein
• Wenn es sich um Attributknoten handelt, müssen Name
und getypter Wert gleich sein
• Bei Text,-Namensraum- und Kommentarknoten muss
der textuelle Wert gleich sein
• Bei Knoten für Verarbeitungsanweisungen müssen
Name und textueller Wert gleich sein
• Bei Elementknoten müssen Attributknoten gleich sein
• Wenn beide Elementknoten einen einfachen Typ haben,
muss der getypte Wert gleich sein
• Wenn ein Elementknoten einen einfachen Typ hat und
der andere nicht sind sie nicht gleich
• Wenn beide Elementknoten einen komplexen
gemischten Inhalt haben, sind sie gleich, wenn ihre
Kindknoten paarweise gleich sind
Zusammenfassung
• XQuery definiert ein eigenes Datenmodell
• Das zentrale Konstrukt ist die Sequenz: Eine Sequenz
kann aus atomaren Werten und Knoten bestehen
• Dann habe ich die atomaren Werte erläutert, i.Z. mit
Konstruktoren und Literale
• Dann kommt das zweite große Komplex, die Knoten, mit
den Knotenarten und Funktionen, die auf Knoten
arbeiten
• Dann die Typabfrage mit instance of und typeswitch
• Und als letztes das Konzept der Gleichheit von
Sequenzen, wobei die Tatsache, dass Knoten als
Einträge einer Sequenz dazu führt, dass die Gleichheit
rekursiv definiert werden muss!
Quellen
• Bild:
www.tutego.de/images/seminare/logos/xm
l.png
• W.Lehner,H.Schöning:XQuery:Grundlagen
und fortgeschrittene Methoden:2004.
ENDE
• GESCHAFFT!!!! 
Herunterladen