Technologie Internetu
wykład 8: Document Type Definitions oraz XML Schema
Piotr Habela
Polsko-Japońska Wyższa Szkoła Technik Komputerowych
W poprzednim odcinku…
• Języki znaczników – SGML jako protoplasta HTML i XML
• Działalność World Wide Web Consortium (W3C):
– Zasady projektowe specyfikacji: współdziałanie, ewolucyjność, decentralizacja.
– Wizja rozwoju Web-u: od prostej architektury (URL, HTTP, HTML), po rozbudowany system standardów opartych na URI, HTTP 1.1 i XML.
• Składnia języka XML:
– Element i jego atrybut;
– Encja;
– Deklaracja (sekcja znakowa, komentarz, inne…);
– Poprawność składniowa dokumentu XML;
– Poprawność strukturalna dokumentu XML.
Plan wykładu
• Przydatność definicji typu dokumentu.
• Document Type Definition (DTD):
– Sposoby umieszczania;
– Deklarowane właściwości;
– Ograniczenia.
• XML Schema – wprowadzenie.
Motywy dla definiowania typu dokumentu
• Skuteczniejsza kontrola błędów przy tworzeniu dokumentu oraz możliwość zaimplementowania podpowiedzi w
edytorach XML.
• Możliwość uzgodnienia formatów dla elektronicznej wymiany dokumentów pomiędzy instytucjami.
• Definiowanie sposobów konwersji pomiędzy dokumentami sporządzonymi w różnych formatach.
• Podstawa dla określania sposobów wizualizacji poszczególnych rodzajów elementów.
Poprawność strukturalna dokumentu XML
• Warunek konieczny – poprawność składniowa.
• Prolog zawierający deklarację DTD albo odwołanie do zewnętrznej DTD.
• Pozostała zawartość dokumentu zgodna z podanym DTD.
• Co może zawierać prolog ?
– Tzw. deklarację XML (określa użytą wersję XML, sposób kodowania znaków oraz samodzielność dokumentu).
– Deklaracje typu DTD.
– Pomiędzy ww. mogą występować instrukcje przetwarzania (PI – Processing Instruction) oraz rozdzielające „znaki białe”
(whitespace).
Tworzenie Definicji Typu Dokumentu
• Definicja wewnętrzna: w postaci pojedynczego bloku DOCTYPE zwanego deklaracją typu dokumentu (document type declaration):
<!DOCTYPE nazwaTypu [ …….. ]>
• Wewnątrz nawiasów kwadratowych znajduje się deklaracja
przynajmniej jednego elementu – stanowiącego element-korzeń
dokumentu. Wyróżnia go nazwa identyczna z nazwą typu dokumentu.
Np.<!DOCTYPE jakisTekst[
<!ELEMENT jakisTekst (#PCDATA)>
]>
• Definicja zewnętrzna: zamiast definicji elementów umieszczanej wewnątrz nawiasów kwadratowych, występuje odwołanie do
zewnętrznego pliku:
<!DOCTYPE nazwaTypu SYSTEM ”osobnyPlik.dtd”>
• Definicje zewnętrzna i wewnętrzna: jako pierwsza zostanie przetworzona lokalna i jej deklaracje mogą przesłonić
(przedefiniować) te pobrane z zewnętrznego pliku.
Definicja typu zewnętrzna
• Identyfikator systemowy: Po słowie kluczowym SYSTEM występuje identyfikator zasobu (URI). Zwykle jest to
względny lub bezwzględny adres URL.
• Identyfikator publiczny: Zamiast słowa kluczowego SYSTEM występuje PUBLIC, a następnie, przed
identyfikatorem zasobu występuje dodatkowo tzw. FPI (Formal Public Identifier), o następującej budowie
(segmenty rozdzielone są podwójnymi ukośnikami: „//”):
– znak + oznaczający definicję stanowiącą standard lub – oznaczający definicję nie będącą standardem;
– nazwa instytucji odpowiedzialnej za specyfikację typu;
– typ dokumentu i nr wersji;
– dwuliterowy kod oznaczający język;
Np. <!DOCTYPE faktura_XYZ
PUBLIC "-//Firma XYZ//Faktura 1.0//PL"
Deklarowanie elementów
• Budowa deklaracji elementu:
– słowo kluczowe ELEMENT;
– nazwa elementu (nazwa identyfikujących go znaczników);
– definicja zawartości.
• Model zawartości elementu:
– zawartość znakowa (tekst);
– zawartość elementowa (określonego rodzaju podelementy);
– zawartość mieszana.
Elementy proste
• Definicja zawartości dla elementu prostego:
– deklaracja elementu pustego: EMPTY;
– deklaracja dowolnej zawartości: ANY;
– deklaracja zawartości tekstowej: (#PCDATA);
Skrót od: Parsed Character Data.
Np. <!ELEMENT tekstowy (#PCDATA)>
<!ELEMENT paragraf ANY>
<!ELEMENT separator EMPTY>
• Zastosowanie elementów pustych:
– jako miejsce przechowywania atrybutów;
– jako przełącznik dla programów przetwarzających.
• Deklaracja zawartości dowolnej (ANY):
– Dowolne, ale zdefiniowane podelementy;
– Zawartość ta (podelementy) dowolnie poprzeplatana zwykłym tekstem.
Zawartość elementowa
• W najprostszej postaci, jest to nazwa elementu zawieranego (podelementu) ujęta w nawias;
• Oznacza to dokładnie jedno wystąpienie takiego podelementu;
• Tę liczność można modyfikować symbolami:
„+” oznacza [1..*], „?” oznacza [0..1], „*” oznacza [0..*].
• Nazwy podelementów (wraz z określeniemi ich liczności) można grupować za pomocą:
– symbolu przecinka => oznacza sekwencję,
– symbolu „|” => oznacza wybór dokładnie jednego z rozdzielonych tak elementów;
• W oparciu o powyższe konstrukcje można tworzyć złożone deklaracje używając nawiasów:
<!ELEMENT firma ((oddział)+ | przedstawicielstwo)>
<!ELEMENT oddział
(dyrektor, handlowiec*, osoba_kontaktowa?)>
Zawartość mieszana
• Może stanowić albo sam tekst (co sprowadza się do zawartości tekstowej),
• … albo dowolna liczba powtórzeń tekstu i podelementów;
• Istnieje istotne ograniczenia na postać deklaracji.
Efektywnie jedyna dozwolona postać deklaracji to:
<!ELEMENT nazwaMieszanego
(#PCDATA | element_1 | element_2)*>
• Czyli, dla takiej grupy wyboru nie można ani pominąć symbolu liczności „*”, ani użyć innego (tj. „?” ani „+”).
Jako pierwszy element wyboru musi ponadto zawsze wystąpić #PCDATA.
Zawartość elementowa - niedogodności
• Podstawową trudnością jest zadeklarowanie jako możliwej zawartości elementowej podzbioru z jakiegoś repertuaru dokumentów.
• Np. konieczność umieszczenia dwóch dokumentów tożsamości, spośród kilku zdefiniowanych rodzajów
=> potrzeba zadeklarować osobno każdą dwuelementową kombinację:
<!ELEMENT tozsamosc ((dowod_osobisty | prawo_jazdy) | (dowod_osobisty, paszport) | (prawo_jazdy, paszport) | (dowod_osobisty, indeks) | (prawo_jazdy, indeks) |
(paszport, indeks))>
• Sekwencja dwóch wyborów byłaby o wiele bardziej zwięzła, ale niestety nie wykluczyłaby powtórzeń.
• Gdyby należało ponadto zapewnić dowolność kolejności umieszczania takich elementów, to rozmiar deklaracji
dodatkowo znacznie wzrósłby.
Deklaracje atrybutów
• Atrybuty występują w postaci par nazwa=”wartość” w otwierających znacznikach XML.
• Deklaracje atrybutów dla danego rodzaju elementu zawarte są w deklaracji ATTLIST odnoszącej się do nazwy
opisywanego elementu.
• Definicja atrybutu składa się z:
– nazwy atrybutu i typu atrybutu;
– wartości domyślnej (lub określenia obowiązkowości występowania).
• np. <!ELEMENT opis (#PCDATA)>
<!ATTLIST opis id ID #IMPLIED
kto_wprowadzil CDATA #IMPLIED>
Zadeklarowano tu element o zawartości tekstowej, który posiada dwa opcjonalne atrybuty: unikalny identyfikator (typ ID) oraz tekst
Atrybuty w XML – dostępne typy
• CDATA – łańcuch znaków;
• ID – unikalna wartość w ramach całego dokumentu. Każdy element może posiadać tylko jeden atrybut takiego typu. Nie może zawierać białych znaków.
• IDREF – odnośnik do identyfikatora. Prosty rodzaj odsyłacza.
• IDREFS – zbiór odsyłaczy do identyfikatorów (rozdzielony spacjami).
• NMTOKEN – pojedyncze słowo – symbol (tylko litery cyfry i wybrane znaki jak „_” „-” czy kropka).
• NMTOKENS – zbiór słów – symboli.
• ENTITY – encja;
• ENTITIES – zbiór encji (rozdzielony spacjami);
• NOTATION – instrukcje podlegające innym regułom składniowym niż XML.
• wyliczeniowy – lista wartości w podana w nawiasie i rozdzielona symbolami „|”.
• xml:nazwa – jako nazwa atrybutu determinuje zbiór jego wartości (zdefiniowany standardem z rodziny XML).
Wartości domyślne atrybutów
• Po specyfikacji typu może wystąpić:
– Wartość domyśna: ”wartość”
– Oznaczenie opcjonalności atrybutu (domyślne, jeśli nie zostało podane inaczej): #IMPLIED
– Oznaczenie obowiązkowości atrybutu: #REQUIRED – Określenie atrybutu jako stałej: #FIXED ”wartość”.
• Naturalnie, wszystkie te opcje wzajemnie się
wykluczają.
Jak modelować właściwości elementu?
• Jako atrybuty czy jako podelementy? Kryteria wyboru:
– charakter umieszczanych danych (cechy charakteryzujące cały element => atrybuty; spójne obiekty podrzędne wobec naszego elementu => podelementy);
– ograniczenia narzucone przez konstrukcję języka.
• Stosowanie podelementów:
– informacja pojęciowo separowalna jako spójny obiekt;
– informacja może się powtarzać (kilka egzemplarzy w naszym dokumencie);
– istotna jest kolejność.
• Stosowanie atrybutów:
– informacje dodatkowe, współzależne z podelementami (np. liczba rozdziałów);
– użycie typu wyliczeniowego dla wartości (np. status dokumentu);
– informacja o stałej wartości;
– istotna jest niepowtarzalność wartości (użycie ID jako typu atrybutu).
Przestrzenie nazw (namespaces)
• Umożliwiają bezkolizyjne korzystanie z niezależnie powstałych definicji elementów i ich atrybutów.
• Deklarowane w postaci:
xmlns:NASZ_PREFIKS=”http://uri.do.naszego/prefiksu”
• URI nie musi wskazywać na plik z definicją typu dokumentu;
jedynie unikalnie identyfikuje daną przestrzeń nazwową. Zaleca się, aby w tym celu nie stosować względnych adresów URL.
• Deklaracja zwykle jest zlokalizowana jako atrybut w korzeniu dokumentu, jako że obowiązuje wówczas dla wszystkich
elementów podrzędnych.
• Użycie: NASZ_PREFIKS:nazwaElementu
• Prefiks xml jest zarezerwowany: predefiniowane atrybuty (xml:lang, xml:space, xml:base) -> zob. dalej.
Domyślne i predefiniowane przestrzenie nazwowe
• Domyślna przestrzeń nazwowa:
– nie wymaga prefiksowania jej elementów w ciele dokumentu;
– deklarowana w postaci xmlns= URI (czyli też bez prefisku).
• Przestrzenie standardowe:
html -> HTML oraz XHTML; xlink -> XLink; xsd -> XML
Schema; xsl -> XSLT; fo -> XSL; mml -> MathML; svg -> SVD;
rdf -> RDF; rdfs -> RDF Schema; ds -> XML Signature.
• Zakłada się, że aplikacja obsługująca dany język
standardowy będzie posiadała wbudowaną jego definicję.
Z kolei dla innych języków URI stanowi zwykle zarazem adres definicji DTD.
Atrybuty predefiniowane języka XML
• xml:lang -> język (narodowy) zawartości danego dokumentu.
Podawany jako dwuliterowy kod wg normy ISO-639, uzupełnione opcjonalnie (według ISO-3166) o dwie litery oddzielone pauzą (wersja języka); np. en-US i en-GB. Kody niestandardowe rozpoczyna „x-”.
• xml:space -> określa sposób traktowania białych znaków. Przybiera wartości: ”default” lub ”preserve”. W tym drugim wypadku znaki białe wewnątrz danego elementu nie będą redukowane.
• Obydwa atrybuty należy zadeklarować w definicji typu elementu (możliwe, że jako stałe lub z wartością domyślną), którego będą dotyczyć.
np. <!ATTLIST faktura xml:lang NMTOKEN ”pl”>
• xml:base -> określa adres URI odniesienia dla adresów względnych.
Powtórne zdefiniowanie tego atrybuty w elemencie podrzędnym spowoduje, że w jego wnętrzu będzie obowiązywało złożenie obu ścieżek.
Encje (entities) – zastosowanie i rodzaje
• Umożliwiają wyodrębnianie i odwoływanie się do nazwanych elementów XML.
• Encje ogólne przetwarzane: odwołania w postaci
&nazwaEncji;
– wewnętrzna: treść zawarta w deklaracji encji; Np.:
<!ENTITY pjwstk ”Polsko-Japońska Wyższa Szkoła Technik Komputerowych”>
– zewnętrzna: treść zawarta w zewnętrznym dokumencie;
<!ENTITY tekstNaglowka SYSTEM "naglowek.txt">
(mechanizm jednostek zewnętrznych rozwijany jest jako XML Inclusions (Xinclude))
• Ogólna zewnętrzna nieprzetwarzana: inna postać
odwołania – nazwa encji jako wartość atrybutu. Zawiera etykietę NDATA a za nią nazwę formatu. Np.
<!ENTITY logo SYSTEM ”NaszeLogo.jpg”
NDATA obraz_jpg>
Encje - rodzaje
• Parametryczna: oznaczana symbolem %. Odwołania do niej mogą występować tylko w ramach tego samego DTD.
Służą określaniu powtarzających się w danym DTD treści.
– wewnętrzna: treść w deklaracji DTD; Np.
<!ENTITY % atrybuty_adresowe ”ulica CDATA #REQUIRED miejscowosc CDATA #REQUIRED kraj CDATA #IMPLIED”>
– zewnętrzna: treść w zewnętrznym pliku DTD. Służy dekompozycji dużego DTD pomiędzy kilka plików.
Np. <!ENTITY % definicja_cennika SYSTEM ”cennik.dtd”>
<!ENTITY % faktura PUBLIC
”-//Nasza Firma//format faktury 1.1//PL” ”faktura.dtd”>
• Wykorzystanie w DTD: %nazwaEncji;
Deklaracja notacji (notation)
• Służy określeniu zawartości o składni różnej od XML.
Innymi słowy – może określać:
– format nieprzetwarzanych encji;
– format elementów;
– aplikacja przetwarzająca daną instrukcję przetwarzania (PI);
• Składa się z nazwy formatu i z adresu przetwarzającego go oprogramowania (możliwy też identyfikator publiczny):
<!NOTATION obraz_jpg SYSTEM ”../apps/viewer.exe”>
• Wykorzystanie w deklaracji nieprzetwarzanej encji zewnętrznej:
<!ENTITY logo SYSTEM ”NaszeLogo.jpg” NDATA obraz_jpg>
• Odwołanie do encji nieprzetwarzanej następuje poprzez jej nazwę w odpowiednim atrybucie:
<rysunek zawartosc=”logo” />
Pozostałe konstrukcje
• Fragmenty deklaracji można ująć w deklarację sekcji warunkowej: <![INCLUDE [ ….. ]]>
– Zamiana słowa kluczowego na IGNORE spowoduje pominięcie danego fragmentu deklaracji.
– Tę podmianę można wspierać encjami parametrycznymi.
• Deklaracja samodzielności dokumentu (standalone declaration) – umieszczana w deklaracji XML.
• Deklaracja taka jest potrzebna z następujących przyczyn:
– deklaracje znaczników (markup declarations) zawarte w DTD mogą wpływać na postać dokumentu (np. wartości domyślne atrybutów, deklaracje encji);
– jeśli deklaracje są zawarte w zewnętrznym DTD, to przez tzw.
parser niewalidujący (czyli parser nie sprawdzający poprawności strukturalnej) zostają pominięte;
• Wobec tego wartość standalone=”no” zmusza do sięgnięcia do tych definicji.
Ograniczenia DTD
• Określenie zawartości elementu jako tekstowej powoduje pełną dowolność co do jego zawartości;
• Elementy nie mogą określać wartości domyślnych;
• Brak ograniczenia na unikalność wartości atrybutu;
• Brak ograniczenia na unikalność zawartości elementu;
• Słabe możliwości kontroli typów;
• Brak możliwości odrębnego definiowania typów wykorzystywanych w różnych miejscach; brak dziedziczenia;
• Niemożność ustalenia kolejności atrybutów;
• Niemożność zmiany kolejności elementów;
• Przestrzenie nazwowe nie są wspierane w DTD;
• Rozbieżności składniowe w stosunku do zwykłego XML.
XML Schema
• Projektowany jako uzupełnienie czy wręcz następca DTD (w przeciwieństwie do niego jest odrębnym językiem).
• Jest w stanie swymi deklaracjami odwzorować dowolną definicję DTD, jednak nie odwrotnie.
• Bardzo rozbudowana specyfikacja. Wydana w 2 częściach:
Struktury (Structures) oraz Typy Danych (Datatypes).
• Znacznie bardziej rozbudowany system typów.
• Możliwość nakładania różnych ograniczeń na dopuszczalne wartości i ich unikalność.
• Wyprowadzanie nowych typów z już istniejących:
mechanizm rozszerzeń (extensions) i ograniczen (constraints).
• Uwzględnienie przestrzeni nazw w definicji schematu.
• I inne…
Deklaracja schematu dokumentu
• W przeciwieństwie do DTD, XML Schema jest osobnym językiem, więc należy wyspecyfikować jego przestrzeń
nazwową. Przypomnijmy, że przewidziano dlań prefiks xsd.
Deklaracja wygląda więc następująco:
<xsd:schema
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
....
</xsd:schema>
• Stosowanie dokładnie tego prefiksu nie jest obowiązkowe (można wybrać inny albo domyślny). Z kolei konieczne jest, aby korzeń definicji był element o nazwie „schema”.
• Deklaracja elementu:
<xsd:element name=”nazwaElementu” type=”xsd:string” />
• Zwróćmy uwagę na typową składnię XML oraz możliwość przypisania precyzyjnie określonego typu zawartości
elementu.
Zawartość definicji schematu
• Sposób deklarowania atrybutu został również dostosowany do zwykłej składni XML. Definicję atrybutu wiążemy z
określonym elementem poprzez zagnieżdżenie tagu:
<xsd:attribute name=”nazwaAtrybutu” type=”xsd:integer” />
• Poza predefiniowanymi typami (znaczny repertuar) istnieje możliwość deklarowania własnych typów.
• Ogólnie zawartość schematu może być następująca:
– deklaracja XML;
– element-korzeń schema;
– definicje typów;
– deklaracje atrybutów i elementów.
Schematy a przestrzenie nazwowe
• W samej definicji schematu możliwe jest jej przypisanie do określonej przestrzeni nazwowej. Służy temu atrybut
targetNamespace.
• Dysponujemy wówczas dwiema przestrzeniami nazwowymi:
– przestrzenią standardowych elementów XML Schema;
– przestrzenią docelową;
• Z kolei, tak jak w każdym dokumencie XML można
określić domyślną przestrzeń nazwową dla występujących w definicji schematu tagów: xmlns=URI przestrzeni
nazwowej.
• Możemy ją przydzielić dla przestrzeni docelowej lub dla przestrzeni XML Schema (dla skrócenia odwołań do
elementów standardowych lub zadeklarowanych lokalnie).
Wymuszanie kwalifikowania elementów
• Możemy określić, czy zdefiniowane lokalnie elementy i atrybuty będą musiały być prefiksowane symbolem
odpowiedniej przestrzeni nazwowej w zgodnych dokumentach:
• Następujące atrybuty w tagu „schema” okeślają sposób działania globalnie:
• elementFormDefault=”qualified” -> dotyczy prefiksowania elementów;
• oraz attributeFormDefauld=”qualified” -> dotyczy
prefiksowania atrybutów (domyślną wartością jest w obu wypadkach ”unqualified”).
• To globalne ustawienie można modifikować atrybutami określanymi dla poszczególnych elementów:
Deklaracja korzenia schematu
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:po="http://www.example.com/PO1"
targetNamespace="http://www.example.com/PO1"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
…
</schema>
• Lokalnie zdefiniowane atrybuty nie będą prefiksowane, zaś lokalnie zdefiniowane elementy będą wymagały
prefiksowania.
Odwoływanie się w dokumentach do schematów
• Bez przestrzeni nazw (sposób częściej stosowany):
<elementKorzen
xmlns:xsi=”http://www.w3c.org/2001/XMLSchema-instance”
xsi:noNamespaceSchemaLocation=
”plikNaszegoSchematu.xsd”>
<!-- może tu też wystąpić URL -->
</elementKorzeń>
• Z przestrzenią nazw:
<naszaNamespace:elementKorzen xmlns:naszaNamespace=
”http://URLnaszejPrzestrzeni.com”
xmlns:xsi=”http://www.w3c.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://URLnaszejPrzestrzeni.com plikNaszegoSchematu.xsd”>
<!-- może tu też wystąpić URL -->
Typy w XML Schema
• Określają rodzaj zawartości elementów oraz atrybutów.
• Wyróżniono 3 zasadnicze rodzaje:
– Typ wbudowany (m.in. wspomniane już string i integer);
– Typ prosty, zdefiniowany w dokumencie za pomocą elementu xsd:simpleType;
– Typ złożony, zdefiniowany w dokumencie za pomocą elementu xsd:complexType. Nie może dotyczyć atrybutów.
• Kategorie wbudowanych typów danych:
– Liczbowe, – Znakowe, – Daty i czasu,
– Logiczne,binarne,
– XML (np. ID, IDREF).