das xquery-datenmodell. gliederung sequenzen atomare werte knoten knoteneigenschaften sequenztypen...
TRANSCRIPT
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 SequenzenSignatur 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 Sequenzen-Funktionen
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, $lastval as xs:integer) as xs:integer*
Sequenz ganzzahliger Werte, die
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 XML- Dokument.
• 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, namespace-uri: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-07-23</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
KnotentypenKnotentyp Bedeutung
node() Beliebiger Knoten
document-node() Ein Dokumentknoten
document-node(element(…)) Ein Dokumentknoten, wobei das Dokument als Wurzelelement ein Element hat
text() Ein Textknoten
comment() Ein Kommentarknoten
processing-instruction()
processing-instruction(Ziel)
Ein Verarbeitungsanweisungsknoten
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//ALet $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 default- Klausel 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/xml.png
• W.Lehner,H.Schöning:XQuery:Grundlagen und fortgeschrittene Methoden:2004.
ENDE
• GESCHAFFT!!!!