XML – ćwiczenia 2: DTD

Definiowanie zastosowań XML

XML jest językiem. Dużo więcej daje jednak spojrzenie na XML jako metajęzyk, to znaczy zbiór języków, zastosowań XML. Na przykład zastosowaniem XML jest XHTML 1.0, to znaczy każdy dokument XHTML jest dokumentem XML, a dodatkowo jest zgodny z defnicją typu dokumentu XHTML.

Do zastosowań XML należą znane standardy, jak XSLT, XHTML czy WSDL. Można także zdefiniować swój własny język – zastosowanie XML. Definiowanie zastosowania XML nazywa się zwykle definiowaniem struktury dokumentu lub typu dokumentu.

Porządna definicja zastosowania XML, analogicznie do definicji języka programowania, powinna zawierać dwie części:

  1. składniową – podanie dopuszczalnych nazw elementów i atrybutów, oraz ich dopuszczalnej zawartości,
  2. semantyczną – określenie znaczenia poszczególnych elementów i atrybutów.

W praktyce formalnie definiuje się jedynie część składniową, służą do tego wymienione poniżej standardy. Natomiast znaczenie elementów i atrybutów opisuje się słownie w oddzielnym dokumencie tekstowym (jak w przypadku rekomendacji W3C), w komentarzach DTD czy schematu, lub niestety nie opisuje w ogóle.

Standardy

Zalecane sposoby definiowania struktury dokumentu:

  • DTD (Document Type Definition) – część standardu XML,
  • XML Schema – rekomendacja W3C.

Alternatywne standardy (jako ciekawostka):

  • Relax NG – standard podobny do XML Schema, mniej rozbudowana i bardziej czytelna składnia ułatwia ręczną edycję,
  • Schematron – odmienna ideologia, typ dokumentu określa się tu nie w oparciu o gramatykę, ale poprzez listę predykatów, które dokumenty muszą spełniać.

Obecnie najbardziej zalecanym standardem do definiowania nowych typów dokumentów jest XML Schema. Istnieje jednak wiele typów dokumentów już zdefiniowanych za pomocą DTD, a czasem, ze względu na specyfikę zastosowania i używane narzędzia, DTD opracowuje się (lub generuje się ze schematów) również dla nowych standardów (np. XHTML).

Dwa stopnie poprawności dokumentu, walidacja

Każdy dokument XML musi być poprawny składniowo (well-formed) – być zgodny z gramatyką XML i spełniać well-formedness constraints wymienione w rekomendacji XML.

Dodatkowo dokument XML może być poprawny strukturalnie (valid) – być zgodny z definicją struktury. Jeśli nie jest powiedziane inaczej, chodzi o DTD, a dokument ma spełniać validity constraints wymienione w rekomendacji XML. Tego samego terminu używa się także do określenia zgodności ze schematem XML Schema bądź innych standardów.

Proces sprawdzania poprawności strukturalnej nazywa się walidacją. Po wykonaniu walidacji mamy pewność, że dokument posiada właściwą strukturę. Dzięki temu, np. we własnych programach czy w arkuszach XSLT, nie musimy już rozważać przypadków błędnych i od razu wiemy, że np. wymagane elementy rzeczywiście występują.

Definicja struktury i proces walidacji mogą mieć wpływ na zawartość dokumentu w warstwie logicznej. Dzieje się tak ponieważ:

  • zarówno DTD jak i schemat XML Schema może określać domyślne wartości atrybutów,
  • na podstawie definicji struktury oraz specjalnego atrybutu xml:space parser może zignorować niektóre białe znaki między elementami,
  • (tylko) DTD może definiować encje, które rozwijają się do określonej zawartości; encje mogą odwoływać się także do zewnętrznych, potencjalnie zmiennych, zasobów.

DTD

Położenie

Deklaracja DTD w dokumencie występuje za deklaracją XML (jeśli istnieje) a przed elementem głównym. Może w całości być zawarta w dokumencie, może być zawarta w encji zewnętrznej, lub częściowo być w encji zewnętrznej, a częściowo w dokumencie - w tym przypadku jako pierwsza przetwarzana jest część wewnętrzna.

Przykład 1.

<?xml version="1.0"?> <!DOCTYPE greeting SYSTEM "hello.dtd">
<greeting>Hello, world!</greeting>
<?xml version="1.0"?> <!DOCTYPE greeting PUBLIC "-//W3C//GREETEING 1.0//EN" "hello.dtd">
<greeting>Hello, world!</greeting>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE greeting [
  <!ELEMENT greeting (#PCDATA)>
]>
<greeting>Hello, world!</greeting>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE greeting SYSTEM "hello.dtd" [
  <!ATTLIST greeting words CDATA #IMPLIED>
]>
<greeting words="2">Hello, world!</greeting>

Elementy

Definiowanie struktury dokumentu w DTD opiera się na założeniu, że w całym dokumencie elementy o tej samej nazwie mają podobną strukturę. DTD definiuje typy elementów, elementami jednego typu są elementy o tej samej nazwie.

DTD pozwala zdefiniować takie własności dokumentu jak:

  • zestaw dopuszczalnych typów elementów (nazwy elementów nie wymienione w DTD nie mogą występować w dokumencie),
  • dla każdego typu elementu pozwala w pewnym stopniu określić jego dopuszczalną zawartość (patrz dalej),
  • dla każdego typu elementu określa jego atrybuty, ich wartości domyślne, obowiązkowość występowania, w pewnym stopniu ich dopuszczalne wartości.

Dla każdej nazwy elementu może istnieć tylko jedna jego deklaracja w DTD. Deklaracja elementu ma postać:

<!ELEMENT nazwa-elementu typ-zawartości-elementu >

Typy zawartości elementu:

ANY
zawartość dowolna,
EMPTY
element zawsze jest pusty,
#PCDATA
zawartość tekstowa,
(#PCDATA | nazwa-elementu1 | nazwa-elementu2 ... )*
model mieszany – zawartość tesktowa z zanurzonymi w niej elementami, bez kontroli kolejności ani liczności wystąpień,
wyrażenie regularne
zbudowane za pomocą ( ) , | ? * + z nazw elementów.

Zadanie 1.

Zapisz deklaracje elementów o następujących typach zawartości:

  1. niezerowa sekwencja elementów a lub niezerowa sekwencja par elementów b i c,
  2. niezerowa sekwencja wyborów: jedno a lub para elementów b i c,
  3. co najmniej trzy elementy a,
  4. ciąg dowolnie wymieszanych a i b, ale zaczynający się i kończący na a (co najmiej jedno a),
  5. dowolna, ale niezerowa liczba następujących sekwencji podelementów: a, od jednego do trzech razy b, opcjonalnie c.

Zadanie 2.

Czy w DTD da się zapisać następujące typy zawartości? Jeśli tak, to podaj rozwiązanie:

  1. od sześciu do dziewięciu elementów a,
  2. elementy imię, nazwisko, nr-indeksu w podanej tu kolejności,
  3. elementy imię, nazwisko, nr-indeksu, ale w dowolnej kolejności,
  4. j.w. ale imion może być od 1 do 3,
  5. tekst z zanurzonymi elementami a, b i c, w podanej kolejności kolejności, wszystkie muszą wystąpić dokładnie raz,
  6. tekst z zanurzonymi elementami a, b i c, w dowolnej kolejności, wszystkie muszą wystąpić dokładnie raz,
  7. tekst z zanurzonymi elementami a, b i c, w dowolnej kolejności, wszystkie mogą wystąpić najwyżej raz,
  8. tekst z zanurzonymi elementami a, b i c, w dowolnej kolejności, wszystkie mogą wystąpić co najmniej raz,
  9. tekst z zanurzonymi elementami a, b i c, w dowolnej kolejności, wszystkie mogą wystąpić dowolną liczbę razy (także zero).

Atrybuty

Deklaracja listy atrybutów ma postać:

<!ATTLIST nazwa-elementu
	nazwa-atrybutu1 typ-zawartości-atrybutu1 opis-domyślnego1
	nazwa-atrybutu2 typ-zawartości-atrybutu2 opis-domyślnego2
	...
>

Dla każdego elementu może być wiele list atrybutów, są łączone. Dla każdego atrybutu może być w sumie wiele deklaracji – liczy się pierwsza.

Typy zawartości atrybutu:

CDATA
dowolny tekst,
ID
nazwa unikalna w całym dokumencie, dla danego typu elementu tylko jeden atrybut może być zadeklarowany jako ID,
IDREF
nazwa występująca gdzieś w dokumencie jako wartość typu ID,
IDREFS
jak IDREF, ale może być wiele nazw rozdzielonych białymi znakami
NMTOKEN, NMTOKENS
jeden lub wiele rozdzielonych białymi znakami tokenów, czyli napisów złożonych z liter, cyfr, znaków - _ :.
(token1 | token2 ...)
jeden z podanych tu tokenów,
ENTITY, ENTITIES, NOTATION
inne typy.

opis-domyślnego określa czy atrybut jest wymagany i jaką ma wartość domyślną:

#REQUIRED
atrybut zawsze musi być określony explicite,
#IMPLIED
atrybut nie musi być podany, nie ma wartości domyślnej,
"wartość-domyślna"
atrybut nie musi być podany, jeśli nie jest, to przyjmowana jest wymieniona tu wartość domyślna,
#FIXED "wartość-domyślna"
atrybut nie musi być podawany, zawsze ma określoną tu wartość domyślną, nie może w dokumencie występować z inną wartością.

Zadanie 3.

Zapisz deklaracje atrybutów:

  1. o dowolnej zawartości tekstowej, nieobowiązkowy,,
  2. o dowolnej zawartości tekstowej, obowiązkowy,,
  3. o dowolnej zawartości tekstowej, z domyślną wartością Ala ma kota,
  4. o wartości należącej do listy mały, średni, duży.

Zadanie 4.

Czy w DTD da się zapisać następujące typy atrybutów? Jeśli tak, to podaj rozwiązanie. Być może jest rozwiązanie zbliżone?

  1. liczba naturalna,
  2. pojedyncza nazwa (w sensie XML),
  3. nazwy rozdzielone spacjami,
  4. jedna nazwa z podanej listy,
  5. dowolna liczba nazw z podanej listy rozdzielonych spacjami,
  6. jeden z podanych napisów (ale niekoniecznie tokenów).

Encje

Encja ma swoją nazwę i wartość – fragment dokumentu. Aby można było użyć danej encji, trzeba ją zadeklarować w DTD (nie dotyczy to pięciu encji predefiniowanych). Procesor XML powinien traktować dokument tak jakby w miejsce referencji do encji wstawił ich wartości.

Referencja do encji ogólnej w dokumencie ma postać &nazwa_encji; i może wystąpić poza DTD, natomiast deklaracja w DTD:

<!ENTITY nazwa-encji wartość-encji>

Może być wiele deklaracji encji o tej samej nazwie, liczy się pierwsza. Wartość encji może być podana bezpośrednio w deklaracji ujęta w znaki " lub ', wtedy encję nazywamy wewnętrzną.

Można też zadeklarować encję zewnętrzną – jest to uogólnienie pliku, jakiś zasób dostępny dla procesora XML. Do identyfikacji encji zewnętrznej służy identyfikator systemowy lub identyfikator publiczny. Encja po wstawieniu jest przetwarzana jako XML, powinna być fragmentem XML dającym się sparsować (jeśli jest znacznik otwierający, powinien być zamykający itp.), ponadto może zaczynać się od deklaracji analogicznej do deklaracji XML, podającej wersję XML i kodowanie. Istieją też encje nieprzetwarzane (tylko zewnętrzne).

Przykład 2.

<!ENTITY wewnetrzna
         "bla bla bla <bla>123</bla>">
<!ENTITY zewnetrzna_id_systemowy
         SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">
<!ENTITY zewnetrzna_id_publiczny
         PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN"
         "http://www.textuality.com/boilerplate/OpenHatch.xml">
<!ENTITY zewnetrzna_nieprzetwarzana
         SYSTEM "../grafix/OpenHatch.gif"
         NDATA gif >

Encja parametryczna to specjalny rodzaj encji, do której referencje pojawiać się mogą wewnątrz DTD. Referencja ma postać: %nazwa_encji;, natomiast deklaracja:

<!ENTITY % nazwa-encji wartość-encji>

Encje parametryczne też mogą być wewnętrzne i zewnętrzne, ale nie ma nieprzetwarzanych. Encje parametryczna i ogólna o tej samej nazwie są różnymi obiektami, mogą istnieć obok siebie. Encji parametrycznych używa się zwykle w celu zdefiniowania w jednym miejscu typu zawartości, który następnie jest używany dla wielu elementów / atrybutów.

Wszystkie encje muszą być zadeklarowane przed jakimkolwiek odwołaniem do nich.

Zadanie 5.

Zapisz DTD opisujące znane z HTML elementy dla list ol, ul, li. Załóżmy, że element główny body może zawierać tekst z zanurzonymi w nim listami, listy tylko elementy wypunktowania (li), a elementy wypunktowania znowu tekst z zanurzonymi listami. W każdym miejscu gdzie dopuszczalny jest tekst, może być on znakowany elementami font z atrybutami size i face. Każdy element może zawierać atrybuty id o typie ID oraz class o typie NMTOKEN.

Użyj encji parametrycznych, aby uniknąć powtarzających się fragmentów kodu (tj. nie wprowadzać dwa razy takiego samego typu zawartości).

Sekcje warunkowe

<![INCLUDE[ fragment DTD ]]>
<![IGNORE[ fragment DTD ]]>

W połączeniu z encjami parametrycznymi stanowią mechanizm do tworzenia sparametryzowanych DTD.

Zadanie 6.

Zmień napisane wcześniej DTD tak, aby dokumenty napisane do poprzedniej wersji dalej się walidowały, natomiast nowe z pewną drobną dodatkową informacją były zgodne z nowy standardem, w którym nie ma elementów font, a są span z atrybutem style. Atrybuty id i class, jak poprzednio, mogą występować we wszystkich elementach.

Użyj sekcji warunkowych i encji parametrycznych.


Valid XHTML 1.1Valid CSS