Transcript Document

Technologie Internetu
wykład 9: XML Schema
Piotr Habela
Polsko-Japońska Wyższa Szkoła
Technik Komputerowych
1
W poprzednim odcinku…
• Zastosowanie definicji typów dokumentów;
• Rozwiązania DTD (Document Type Definition):
–
–
–
–
–
–
–
–
Definicja zewnętrzna lub wewnętrzna;
Rodzaje odwołań do zasobów zewnętrznych;
Elementy proste (znakowe, puste, dowolne);
Modele zawartości elementowej (liczności, wybór, sekwencje);
Deklaracje elementów: dostępne typy oraz wartości domyślne;
Rodzaje encji (entities) w XML;
Rola przestrzeni nazwowych (namespaces);
Ograniczenia DTD.
• XML Schema:
– Rozbudowany system typów;
– Obsługa przestrzeni nazwowych.
2
Plan wykładu
• Budowa dokumentu XML Schema:
• Najważniejsze możliwości XML Schema;
– Deklarowanie atrybutów i zawartości elementowej;
– Typy wbudowane XML Schema;
– Tworzenie typów pochodnych:
poprzez ograniczenia i poprzez rozszerzenia;
– Sposoby organizowania podelementów;
– Ograniczenia unikalności;
– …
• Język XPath:
–
–
–
–
Sposoby nawigacji;
Skróty;
Predykaty;
Dostępne operacje.
3
XML Schema – podstawowe informacje
• Instance document oznacza dokument zbudowany zgodnie z daną
specyfikacją schematu.
• Dokument-wystąpienie nie musi obowiązkowo odwoływać się do
swojej specyfikacji schematu.
• Schematy XML Schema są zwykle umieszczane w odrębnych plikach
– zwyczajowo z rozszerzeniem .xsd. Ten skrót jest również używany
do oznaczenia przestrzeni nazwowej (namespace), obejmującej
standardowe elementy XML Schema.
• Definicja schematu zawarta jest w elemencie-korzeniu XML o nazwie
schema:
<xsd:schema> … </xsd:schema>
• Deklaracja elementu oraz atrybutu (lokalnie wewnątrz odpowiednich
elementów lub globalnie, celem wielokrotnego użycia):
<xsd:element name=“nazwaElementu“ type=”typElementu” />
<xsd:attribute name=“nazwaAtrybutu“ type=”typAtrybutu” />
4
Składniki definicji schematu
• Obok deklaracji elementów i atrybutów, istnieje możliwość
globalnego zdefiniowania:
 własnego typu prostego. Wówczas zawartością definicji
typu jest ograniczenie któregoś z wbudowanych typów
prostych (zob. dalej):
<xsd:simpleType name="IdentProduktu">
...
</xsd:simpleType>
 … oraz typu złożonego. W tym wypadku wewnątrz mogą
znaleźć się deklaracje podelementów oraz atrybutów.
<xsd:complexType name="DaneAdresowe">
...
</xsd:complexType>
5
Kompozycyjność definicji schematów
• Deklaracje atrybutów mogą występować w ramach definicji
typu złożonego albo w ramach definicji elementu.
• Deklaracje elementów mogą występować globalnie, w
ramach definicji typu złożonego albo w ramach definicji
innego elementu.
• Definicje typów mogą wystąpić globalnie (z nadaniem
nazwy atrybutem name) albo wewnątrz deklaracji
opisywanego przezeń elementu (anonimowo, celem
jednorazowego wykorzystania w miejscu definicji);
• Zwróćmy uwagę na to kluczowe rozróżnienie:
– Definicje typów tworzą nowe typy dostępne do wykorzystania;
– Deklaracje elementów określają nazwy i typy elementów i
atrybutów, które mogą pojawić się w odpowiednich miejscach
dokumentu.
6
Definicje typów a elementy złożone
• Definicja typu – umieszczona w korzeniu schematu:
– można się doń potem odnosić w deklaracjach elementów w sposób
analogiczny jak dla atrybutów prostych => czytelniejsze deklaracje
oraz ponowne użycie definicji typów;
• Definicja typu złożonego:
– konstruowana elementem xsd:complexType;
– może zawierać deklaracje elementów, atrybutów oraz referencji do
elementów;
– nie może być użyta w deklaracjach atrybutów;
• Deklaracja elementu poprzez podanie typu:
– Podanie w atrybucie type nazwy globalnie zdefiniowanego typu;
• Deklaracja poprzez referencję:
– powoduje wstawienie do bieżącej deklaracji globalnie
zadeklarowanego elementu o podanej nazwie:
<xsd:element ref="adres" minOccurs="0"/>
7
Deklarowanie zawartości elementowej
• Zarówno w definicjach globalnych typów jak i w
deklaracjach elementów złożonych, podelementy
definiujemy wewnątrz elementu xsd:complexType.
• Ograniczenia na liczbę wystąpień podelementów:
– domyślnie dolną a zarazem górną granicą liczności jest
„dokładnie 1”;
– liczności te można modyfikować za pomocą atrybutów: elementu
minOccurs i maxOccurs, których wartościami muszą być liczby
naturalne. Wartością specjalną dla atrybutu maxOccurs może być
ponadto ”unbounded”.
– Deklaracje liczności nie są dozwolone dla elementów globalnych.
8
Deklarowanie atrybutów
• Atrybuty (poza globalnymi) deklarujemy wewnątrz elementu
xsd:complexType.
• Mogą posiadać wyłącznie typy proste.
• Występowanie atrybutu określone jest atrybutem (tj. atrybutem
w elemencie xsd:attribute) use, mogący przybierać wartość:
”optional”, ”required” lub ”prohibited”.
Domyślną deklaracją (przy pominięciu) jest ”optional”.
• Domyślną wartość atrybutu można przypisać stosując atrybut
defalut. Atrybut use musi wówczas przybrać wartość ”optional”.
• Wymuszenie stałej wartości atrybutu osiągamy poprzez zastosowanie
w jego deklaracji atrybutu fixed=”wartość”. Wówczas, jeśli atrybut
jest opcjonalny, wymagana jest albo jego nieobecność w wystąpieniu
albo jego wystąpienie ze zgodną wartością.
• Atrybut default stosuje się też w deklaracjach elementów. Tu jednak
podstawienie wystąpi tylko wtedy, gdy w dokumencie dany element
pojawi się bez zawartości (jeśli nie wystąpi w ogóle, to do
podstawienia nie dojdzie).
9
Typy wbudowane
• Specyfikacja określa wiele wbudowanych typów prostych.
Część z nich zdefiniowano poprzez nałożenie restrykcji na
definicje bardziej podstawowe. Niektóre typy wbudowane:
– string, normalizedString, token, byte, unsignedByte
– positiveInteger, negativeInteger, nonPositiveInteger,
nonNegativeInteger
– integer, long, decimal, float, boolean
– base64Binary ->
każde 6 bitów kodowane symbolem
alfanumerycznym;
time
- np. 13:20:00.000, 13:20:00.000-05:00
– dateTime
- np. 1999-05-31T13:20:00.000-05:00
– duration
- np. P1Y2M3DT10H30M12.3S
– date (oraz ich wycinki) - np. 1999-05-31
– anyURI
- np. http::/www.w3c.org/
– language
- np. en-US, pl
– ID, IDREF, IDREFS, NOTATION…
10
Definiowanie typów pochodnych przez ograniczenia
• Tworzeniu pochodnych typów prostych poprzez nakładanie
ograniczeń służy element xsd:restriction, umieszczany
wewnątrz elementu xsd:simpleType.
• Element restriction zawiera atrybut base, określający typ
bazowy definicji. Może zawierać szereg podelementów,
określanych jako constraining facets (aspekty
ograniczające).
• Np. dla typów liczbowych można użyć elementów
xsd:maxExclusive i xsd:minInclusive z atrybutem
value=”warośćLiczbowa”. Np.
<xsd:simpleType name="numerWewnetrzny">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="10000"/>
<xsd:maxInclusive value="99999"/>
</xsd:restriction>
</xsd:simpleType>
11
Inne aspekty ograniczające (1)
• Dla atrybutów xsd:string i pochodnych można
sformułować wzorzec przy użyciu wyrażeń regularnych:
umieszczamy podelement xsd:pattern z atrybutem
value=”wyrażenieRegularne”.
• Np. "\d{3}-[A-Z]{2}" oznacza trzy cyfry dziesiętne, myślnik
oraz dwie wielkie litery.
<xsd:simpleType name="kodProduktu">
<xsd:restriction base="xsd:string">
<xsd:pattern value="\d{3}-[A-Z]{2}"/>
</xsd:restriction>
</xsd:simpleType>
• Wyrażenia regularne posiadają bardzo bogate możliwości.
M. in. można odwoływać się do różnych kategorii znaków
Unicode.
12
Inne aspekty ograniczające (2)
• Kolejną możliwością jest podanie dozwolonych wartości
danego typu w postaci wyliczenia (enumeration). Służą
temu podelementy xsd:enumeration z atrybutami value:
<xsd:restriction base="xsd:string">
<xsd:enumeration value=„PLN"/>
<xsd:enumeration value=„USD"/>
</xsd:restriction>
• Dla typów liczbowych można określać łączną liczbę cyfr
oraz liczbę cyfr po przecinku:
xsd:totalDigits, xsd:fractionDigits
• Można określać długość albo jej limity: maksymalny i
minimalny:
length, albo maxLength i minLength
Dla typu string oznaczać to będzie liczbę znaków (np. kody walut),
dla typów binarnych – liczbę oktetów, zaś dla list – ich rozmiar.
13
Właściwości aspektów ograniczających
• Łączenie aspektów ograniczających:
– aspekty wzorca współistniejące dla danej definicji z typem
wyliczeniowym są traktowane alternatywnie (suma logiczna);
– inne kombinacje aspektów ograniczających stanowią warunek w
postaci iloczynu logicznego.
• Blokowanie właściwości aspektów – uniemożliwi
redefinicję danego ograniczenia w typie pochodnym:
fixed=”true”;
• Ograniczenia można też stosować do typów złożonych. W
tym wypadku wyprowadzanie poprzez zawężenie liczby
wystąpień wymaga ponownego podania całej ich
zawartości. Jednakże korzyścią pozostaje w takim wypadku
zgodność typologiczna z nadtypem.
14
Typy pochodne – pozostałe możliwości
• Rozszerzenia: przypominają specjalizację klas w językach
programowania.
• Składnia analogiczna jak w wypadku ograniczeń. Zamiast
xsd:constraint stosuje się xsd:extension:
<xsd:extension base=”typBazowy”> . . . </xsd:extension>
• Wprowadzone w ramach rozszerzenia podelementy muszą
być w wystąpieniach dołączane na końcu.
• Blokowanie wyprowadzeń (deklaracje atrybutem final):
Można zabronić wyprowadzania typów, umieszczając w
ich definicji atrybut final z wartością
”#restriction”, ”#extension” lub ”#all”.
15
Organizacja podelementów
• Podelementy mogą być grupowane (za pomocą znaczników
zwanych compositors) w kompozycje trzech rodzajów:
– Sekwencja: wszystkie podelementy muszą wystąpić dokładnie w
podanej kolejności: <xsd:sequence> . . . </xsd:sequence>
– Wybór: musi wystąpić dokładnie jeden z wymienionych
podelmentów: <xsd:choice> . . . </xsd:choice>
– Zbiór: wszystkie zawarte elementy muszą wystąpić, jednakże ich
kolejność jest dowolna <xsd:all> . . . </xsd:all>
• Kompozycje choice i sequence mogą być wzajemnie
zagnieżdżane. Można też określać dla nich liczności
(minOccurs i maxOccurs).
• Ograniczenia kompozycji all:
–
–
–
–
Tutaj dozwoloną licznością jest tylko 1 (domyślnie) albo 0..1.
Nie można zagnieżdżać w nim innych kompozycji.
Nie może też być zagnieżdżany w innej kompozycji.
Stosowanie w rozszerzeniach – tylko gdy element bazowy jest pusty.
16
Zawartość prosta z atrybutami
• Musimy użyć complexType (a nie simpleType), gdyż ten
pierwszy nie pozwala na zdefiniowanie atrybutów.
Wewnątrz complexType umieszczamy:
<xsd:simpleContent> . . . </xsd:simpleContent>
• Zawartość prosta takiego elementu musi zostać
wprowadzona poprzez rozszerzenie (xsd:extension),
atrybutem base: base=”nazwaTypuProstego”. Wówczas
z typu bazowego pochodzi określenie zawartości elementu
(np. xsd:string), zaś rozszerzenie wprowadza potrzebne
nam atrybuty.
17
Grupy elementów i atrybutów
• Ograniczają nadmiarowość definicji schematu.
• Zastosowanie (ograniczenie nadmiarowości i uczynienie
schematów bardziej przejrzystymi) odpowiada encjom
parametrycznym z DTD.
• Do zadeklarowania grupy stosowane są elementy
odpowiednio: <xsd:group> … </xsd:group> oraz
<xsd:attributeGroup> ... </xsd:attributeGroup>,
posiadające atrybut name.
• Odwołaniom do takich grup służą te same elementy
występujące w postaci elementów pustych z atrybutem ref.
18
Ograniczenia unikalności (1)
• W wypadku DTD jedynym (mało elastycznym) środkiem
zapewnienia unikalności było użycie typu ID.
• Ograniczenia unikalności deklaruje się na końcu deklaracji
elementu, którego dotyczą, albo w elementach nadrzędnych
(najczęściej umieszczane są w końcu elementu korzenia
(xsd:schema).
• Postać ograniczenia:
<xsd:key name=”nazwaNaszegoKlucza”>
<xsd:selector
xpath=”elementwRamachKtoregoZapewniamyUnikalnosc” />
<xsd:field xpath=”poleKlucza”/> <!-- atrybut lub podelement -->
… <!-- klucz może być złożony -->
</xsd:key>
19
Ograniczenia unikalności (2)
• Selektory i pola wskazujemy używając atrybutu xpath. Jak sugeruje
nazwa, identyfikuje on zawartość dokumentu XML w sposób
określony specyfikacją XPath.
• Jak zobaczymy, ograniczenia na miejsce występowania deklaracji
unikalności wynikają właśnie z założeń specyfikacji XPath.
• Podobne do ograniczenia xsd:key jest xsd:unique. To drugie
odróżnia się dopuszczalnością pustych elementów (i niepowtarzalność
sprawdza się wówczas tylko pośród niepustych elementów).
• Zarówno ograniczenie unikalności jak i ograniczenie klucza mogą
dotyczyć wartości złożonych.
• Integralność referencyjna – określa zależność klucza obcego.
Przedmiotem odwołania musi być wartość zadeklarowana jako klucz.
• Deklarowane za pomocą elementu keyref:
<xsd:keyref refer=”nazwaKlucza”> . . . </xsd:keyref>
• Atrybut refer określa, do jakiego klucza odwołują się referencje.
• Selektor i pole (lub pola) są deklarowane analogicznie jak w wypadku
kluczy i wartości unikalnych.
20
Definiowanie list
• Zawartością elementu a także atrybutu może być kolekcja
wartości typu prostego, rozdzielona znakami białymi.
• Tego rodzaju zawartość deklaruje się jako listę (list)
określonego typu bazowego.
• Listy nie mogą składać się z innych list.
• Deklaracje – za pomocą elementu xsd:list:
<xsd:list itemType=”nazwaTypuZawartosci” />
• Listy mogą składać się jedynie z wartości (jednego) typu
prostego.
21
Wariantowe definicje typów (unie)
• Dopuszczalne wartości typów prostych można definiować
jako sumę wartości dopuszczanych przez dwa lub więcej
typów.
• Deklaracji takich typów służą unie (unions). Wewnątrz
elementu <xsd:union> . . . </xsd:union> umieszczane są
dwie lub więcej definicje typu;
• Jeśli zaś potrzebne typy zostały już zadeklarowane
globalnie, można się odwołać do ich nazw w atrybucie
memberTypes:
<xsd:union memberTypes=”nazwaTypu1 nazwaTypu2”/>
• W efekcie uzyskujemy nowy typ prosty mogący przybierać
wartość zgodną z dowolnym z wymienionych typów.
• Przykład zastosowania w XML Schema: atrybut
maxOccurs
22
Synonimy oraz byty abstrakcyjne
• Aby dla definicji danego elementu umożliwić tworzenie
jego wystąpień pod różnymi nazwami (synonimy lub wersje
językowe), stosowane są tzw. grupy substytucji
(substitutionGroups).
<xsd:element name=”znizka” type=”xsd:decimal” />
<xsd:element name=”upust” substitutionGroup=”znizka”
type=”xsd:decimal” />
• Elementy służące tylko jako podstawa dla grupy substytucji
oraz typy służące wyłącznie jako podstawa dla definicji
innych (poprzez rozszerzenie lub ograniczenie), możemy
zadeklarować jako abstrakcyjne. Stosujemy w tym celu dla
nich atrybut abstract: abstract=”true”.
23
Sposoby budowy schematów - podsumowanie
• Poprzez zagnieżdżanie: definicje potrzebnych typów
tworzone anonimowo na potrzeby poszczególnych
deklaracji.
• Płaski katalog elementów: elementy tworzące hierarchię są
deklarowane globalnie, zaś w ich docelowych miejscach
występowania w schemacie stosuje się odwołania do tych
globalnych deklaracji.
• Definiowanie typów: globalnie są definiowane nazwane
typy, wykorzystywane następnie w deklaracjach elementów
i atrybutów. Metoda najskuteczniej ogranicza
nadmiarowość, choć wprowadza pewien narzut, wobec
czego nadaje się szczególnie dla bardziej rozbudowanych
schematów.
24
XPath – nawigacja w strukturze dokumentu
25
XPath - charakterystyka
• Język deklaratywny służący wskazywaniu elementów,
atrybutów, lub całych fragmentów dokumentu XML.
• Posiada zwięzłą nie-XML-ową składnię, przyjętą w celu
umożliwienia umieszczania wyrażeń XPath w wartościach
atrybutów oraz w URI.
• Typy zwracanych wartości:
–
–
–
–
boolean;
number (liczba zmiennoprzecinkowa);
string;
node-set (zbiór węzłów).
• Ścieżka (ciąg określający) XPath jest zbudowana z tzw.
kroków (step), oddzielonych symbolem „/”.
• Krok może reprezentować: element, atrybut lub funkcję.
Poszczególne kroki zawężają obszar przeszukiwania.
26
Kontekst wyrażenia XPath
• Wyrażenia danego kroku działają w kontekście określanym
przez kroki poprzednie.
• Na kontekst składają się:
– Bieżący węzeł (tzw. context node);
– Dwie dodatnie liczby naturalne (pozycja kontekstu - context
position oraz rozmiar kontekstu - context size);
– Wiązania zmiennych;
– Biblioteka dostępnych funkcji;
– Zadeklarowane przestrzenie nazwowe widoczne w zakresie
wyrażenia.
• Można podawać alternatywne ścieżki w postaci tzw. wzorca
(pattern). Poszczególne ścieżki są wówczas porozdzielane
symbolami „|”.
27
Relacje pomiędzy węzłami
• XPath operuje na drzewie węzłów XML, czyli na strukturze
hierarchicznej. Węzłem jest element XML wraz z jego
zawartością. Można wyróżnić następujące zależności
pomiędzy węzłami:
– rodzic (parent) – dziecko (child) => pomiędzy elementem
nadrzędnym a jego podelementem;
– rodzeństwo (sibling): poprzednik-następnik
=> określa kolejność występowania elementów tego samego
poziomu;
– przodek (ancestor) – potomek (descendant): rozszerzenie relacji
rodzic-dziecko na zależności pośrednie;
28
Kierunki nawigacji
• Dostępne są następujące słowa kluczowe - operatory stosowane do
selekcji elementów (zwane osiami (?) (axes)):
– self – aktualny węzeł (zwany kontekstem: context node);
– parent – rodzic aktualnego węzła;
(Tylko dwa powyższe zwracają wyniki nie będące nigdy kolekcjami.)
– child – bezpośrednie podelementy;
– descendant – całe drzewo podelementów poniżej aktualnego;
– descendant-or-self – j.w. plus aktualny węzeł;
– ancestor – przodkowie aktualnego węzła;
– ancestor-or-self – j.w. plus aktualny węzeł;
– following-sibling – kolejne węzły na tym samym poziomie hierarchii;
– preceding-sibling – wcześniejsze węzły na tym samym poziomie;
– following – wszystkie węzły zdefniowane za węzłem aktualnym w
dokumencie (bez potomków i węzłów atrybutów oraz przestrzeni
nazwowych);
– preceding – wszystkie węzły zdefiniowane przed węzłem aktualnym
(bez przodków i węzłów atrybutów oraz przestrzeni nazwowych);
29
Budowa kroku XPath
Składnia pojedynczego kroku jest następująca:
• kierunek (axis);
• podwójny dwukropek: “::”
• symbol „*” albo nazwa elementu, albo funkcja:
–
–
–
–
node()
text()
comment()
processing-instruction() <- może zawierać nazwę szukanej
instrukcji przetwarzania;
• dowolna liczba predykatów umieszczonych w nawiasach
kwadratowych: „[ ]”
• Przykłady kroków:
child::*
child::section[position()=2]
ancestor::processing-instruction()
30
Skróty dla typowych kroków XPath
Pełna postać
Skrót
parent::node()
..
/descendant-or-self::node()
//
self::node()
.
attribute::
@
[position()=2]
[2]
(Symbol „/” oznacza korzeń dokumentu.)
• Ponadto child jest kierunkiem domyślnym i wobec tego
może być pominięty. Zatem zapisowi:
/descendant-or-self::node()/child::para
odpowiadać może
//child::para a w konsekwencji //para.
31
Wykorzystanie skrótów
• Uwaga: Globalne wyszukiwania mogą być w swej skróconej postaci
nieco mylące. Np. ścieżka
/descendant::para[1]
zwróci „pierwszy z brzegu” element para, zaś
//para[1]
zwróci wszystkie elementy para występujące jako pierwsze
podelementy swoich rodziców.
• Ważną rolę odgrywa również skrót “.”, będący odpowiednikiem
self::node(). Wraz ze skrótem „//” pozwala na zwięzłe sformułowanie
wyrażenia przeszukującego gałęzie począwszy od bieżącego
elementu:
self::node()/descendant-or-self::node()/child::para
odpowiada .//para
• Podobnie, krok „..” jest skrótem od parent::node(). Np.. ../tytul
zastępuje parent::node()/child::title (selekcjonuje potomne elementy
tytul).
32
Predykaty wyszukiwania
• Predykaty zmieniają pozycję kontekstu i rozmiar kontekstu.
• Występują opcjonalnie, umieszczane wewnątrz nawiasów
kwadratowych celem zawężenia zwróconego zbioru
elementów.
• Muszą zwracać wartość logiczną.
• Dostępne operatory logiczne:
=
!=
>
>= &lt; &lt;= and or
not
• Dostępne operatory arytmetyczne:
+
*
div mod
• Np.
//produkt[cena*1.22 < 1000]
• Jak już wspomniano można wyszukiwać węzły wg ich
pozycji, podając predykat np. [position()=2], skracalny do
postaci [2] (możliwe także inne porównania, np. „>=”).
33
Operacje stosowalne w predykatach XPath (1)
• Operacje na łańcuchach tekstowych:
–
–
–
–
–
–
–
–
concat(łańcuch1, łańcuch2, …)
contains(łańcuch, wzorzec)
normalize-space(łańcuch)
starts-with(łańcuch, wzorzec)
string-length(łańcuch)
substring(łańcuch, od, do),
substring-after(łańcuch, wzorzec),
substring-before(łańcuch, wzorzec), translate(łańcuch, stare,
nowe),
– string(…) => konwersja na string;
34
Operacje stosowalne w predykatach XPath (2)
• Operacje na liczbach:
– ceiling(liczba), floor(liczba), round(liczba),
– sum(zbiór_węzłów),
– number(…) -> konwersja;
• Operacje na wartościach logicznych:
– false(), true(), not();
– boolean(…) -> konwersja;
• Operacje na węzłach:
–
–
–
–
–
count(zbiór_węzłów)
last()
position()
id(identyfikator) -> wyszukanie węzła według indentyfikatora;
local-name(element), name(element),
namespace-uri(element).
35
Ograniczenia języka XPath
• Nie można wyszukiwać łańcuchów rozciągających się
poprzez kilka elementów;
• Niemożność wskazania na znaczniki początkowy i
końcowy;
• Niemożność wyszukiwanie encji i sekcji CDATA;
• Niemożność wskazywania punktów lub zakresów w
tekście.
• Specyfikacja XPointer, przyjmująca nieco inny model
dokumentu, uzupełnia te braki.
36