Specyfikacja#

DTD#

Definicję typu dokumentu (DTD) opisałem już w rozdziale "Doctype". Były to podstawowe informacje dla początkujących webmasterów, dzięki którym mogli oni tworzyć strony zgodne z ogólnie przyjętymi, jak najlepszymi praktykami. W tym miejscu poświęcę więcej czasu na samą budowę DTD, dzięki czemu samodzielne czytanie pliku nie będzie stanowiło problemów.

Umiejętność czytania DTD może nam zastąpić każdy wykaz elementów podawany na stronach poświęconych językowi HTML. Wystarczy mieć plik DTD pod ręką a składnia HTML-a nie ukryje przed nami żadnych tajemnic.

Podstawy#

DTD (Document Type Definition) jest rodzajem dokumentu, który definiuje formalną strukturę innych dokumentów XML, XTHML, HTML lub innych pochodzących z rodziny SGML lub XML. Definicje DTD mogą być zawarte bezpośrednio w danym dokumencie, którego strukturę definiują, ale zazwyczaj zapisywane są w osobnym pliku tekstowym, co pozwala na zastosowanie tego samego DTD dla wielu dokumentu (analogicznie jak w przypadku zewnętrznych arkuszy stylów czy skryptów).

DTD określa składnię konkretnej aplikacji XML lub SGML, np. HTML, EAD, TEI lub innej, zdefiniowanej dla potrzeb użytkowników. Zazwyczaj DTD definiuje każdy dopuszczalny element dokumentu, jego zbiór atrybutów i dopuszczalne wartości. DTD określa także zagnieżdżanie i wymagalność poszczególnych elementów w dokumencie.

DTD powinien dostarczyć aplikacji klienckiej (np. przeglądarce internetowej) istotnych informacji o składni języka użytego do utworzenia dokumentu. Na jego podstawie przeglądarka powinna wiedzieć, w jaki sposób przetworzyć dany dokument. W praktyce jednak przeglądarki mają domyślnie zdefiniowane reguły przetwarzania dokumentów i żadna deklaracja DTD na początku strony tego nie zmienia.

Sam DTD jako schemat opisu dokumentów ma małe możliwości. Istnieją dużo lepsze rozwiązania np. XML Schema czy RelaxNG.

Wewnętrzny DTD#

Jeśli definicja DTD znajduje się wewnątrz dokumentu powinna być umieszczana według następującego schematu:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!DOCTYPE root-element [element-declarations]>
gdzie "root-element" definiuje korzeń dokumentu (czyli pierwszy nadrzędny element). W miejsce "element-declarations" wpisywane są poszczególne definicje dla każdego elementu.

Prosty przykład poprawnego DTD:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE osoba [
	<!ELEMENT osoba (imie, drugieImie, nazwisko)>
	<!ELEMENT imie (#PCDATA)>
	<!ELEMENT drugieImie (#PCDATA)>
	<!ELEMENT nazwisko (#PCDATA)>
]>

<osoba>
	<imie>Grzegorz</imie>
	<drugieImie>Stachu</drugieImie>
	<nazwisko>Brzęczyszczykiewicz</nazwisko>
</osoba>

Działanie powyższego przykładu najlepiej przetestować za pomocą pliku testowego. By odczytać DTD wystarczy wybrać z menu kontekstowego przeglądarki "Pokaż źródło strony".

Zewnętrzny DTD#

Oprócz metody umieszczania DTD bezpośrednio w dokumencie można także stosować odwołanie do zewnętrznego pliku na dwa sposoby:

Prosty przykład dla zewnętrznego DTD:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE osoba SYSTEM "external.dtd">

<osoba>
	<imie>Grzegorz</imie>
	<drugieImie>Stachu</drugieImie>
	<nazwisko>Brzęczyszczykiewicz</nazwisko>
</osoba>

Mieszany DTD#

Możliwe jest także połączenie zewnętrznego i wewnętrznego DTD:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" [
	<!-- wewnętrzne deklaracje -->
]>

<html>
...
</html>

Co ciekawe, DTD może w ogóle nie zawierać żadnych deklaracji:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html>

<html>
...
</html>

W takie sytuacji DTD po prostu określa, że dokument ma jeden element najwyższego poziomu (single top-level element).

Jednostki leksykalne DTD#

W opisie DTD języka HTML występują cztery rodzaje zapisów:

Zapisy ELEMENT oraz ATTLIST nazywa się deklaracjami, natomiast ENTITY - makrodefinicjami.

Komentarze#

Jak w każdym języku programowania lub opisu dokumentów, komentarze przydają się do słownego wyjaśnienia danego fragmentu. W DTD komentarze umieszczamy pomiędzy parą znaków ("--") a ("--") . Prosty przykład:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!
	-- pierwszy poprawny komentarz DTD --
	--
	 drugi
	 poprawny
	 komentarz DTD
	--
>

Komentarze mogą rozciągać się na wiele linii. Mają charakter tylko i wyłącznie informacyjny.

Makrodefinicje ENTITY#

Makrodefinicje pozwalają zdefiniować pewien tekst (w krótszej formie), którego rozwinięcie będzie umieszczone w innym miejscu DTD. Dzięki nim cała definicja staje się zwięzła i bardziej czytelna. Wszystkie makra podzielono na podstawowe grupy i umieszczono na początku DTD. Krótki przykład:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!ENTITY % heading "H1|H2|H3|H4|H5|H6">

Powyższy zapis jest makrodefinicją ustalającą znaczenie napisu % heading.

Makrodefinicja rozpoczyna się od znaków <!ENTITY % po których występuje nazwa, następnie wewnątrz cudzysłowów "..." umieszcza się rozwinięcie nazwy, po czym zamyka całe polecenie znakiem >.

Wywołanie takiej makrodefinicji w DTD następuje poprzez użycie znaku procenta ("%"), po którym podaje się nazwę makrodefinicji, i całą konstrukcję kończy znakiem średnika (";"), przykładowo:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!ELEMENT (%heading;)  - - (%inline;)* -- heading -->

Wewnątrz rozwinięcia nazwy makrodefinicji (między cudzysłowami) mogą pojawić się odwołania do innych makrodefinicji, np:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!ENTITY % inline "#PCDATA | %fontstyle; | %phrase; | %special; | %formctrl;">

Najczęściej stosowanymi makrami będą definicje dzielące elementy HTML na dwie grupy: elementy tekstowe - %inline;, oraz elementy blokowe - %block;, jak również trzy główne grupy atrybutów %coreattrs;, %i18n; i %events;.

Czytanie DTD z wieloma makrodefinicjami może nieco męczyć, ze względu na umieszczenie makr na samym początku DTD. Najlepiej otworzyć sobie dwa osobne okna z plikiem DTD, w pierwszym analizujemy konkretny fragment, a w drugim mamy podgląd na makra.

Oczywiście makrodefinicje DTD nie mogą pojawić się w treści dokumentów xHTML. Pewnym rodzajem makr dla tych plików będą encje, które szczegółowo opisałem wcześniej. Same encje dla HTML-a zostały zadeklarowane w osobnych plikach, w których zastosowano podobną składnię z DTD. Krótki przykład:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!ENTITY lt CDATA "&#60;" -- less-than sign, U+003C ISOnum -->

Deklaracje ELEMENT#

Większa część DTD dla HTML-a składa się z deklaracji elementów oraz ich atrybutów. Deklaracja elementu rozpoczyna się od znaków <!ELEMENT a kończy znakiem >. Wewnątrz niej muszą zostać określone:

  1. Nazwa elementu.
  2. Czy znaczniki otwierający i zamykający są dopuszczalne, wymagane czy opcjonalne. Oznacza się to przez umieszczenie konkretnych znaków zaraz po nazwie. Oto możliwości:
    • "- -" - dwa minusy oznaczają, że znaczniki otwierający i zamykający są obowiązkowe.
    • "- O" - jeden minus, po którym następuje litera "O" oznacza, że znacznik otwierający jest obowiązkowy a znacznik zamykający jest opcjonalny
    • "- O" EMPTY - wzmocniona zasada, która mówi, że znacznik zamykający musi zostać pominięty.
    • "O O" - dwie następujące po sobie litery "O" oznaczają, że znaczniki otwierający i zamykający są opcjonalne.
  3. Zawartość elementu (jeśli w ogóle posiada). Poprawna zawartość dla elementu określana jest mianem wzorca zawartości (content model). Elementy, które zostały zdefiniowane bez żadnej zawartości nazywa się elementami pustymi. Zawartość takiego elementu deklarowana jest przez słowo EMPTY.

Oto prosty przykład definiujący obraz:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!ELEMENT IMG - O EMPTY	-- Embedded image -->

Polecenie deklaruje element IMG, który jest pusty (nie ma żadnej zawartości), dodatkowo znacznik zamykający jest zabroniony.

Definicja wzorca zawartości (content model)#

Wzorzec zawartości definiuje prawidłową zawartość każdego elementu. Może obejmować:

Wzorzec zawartości można tworzyć za pomocą wielu operatorów, które pozwalają ustalić liczbę powtórzeń (kardynalność) dla elementu (lub elementów). Operatory można używać także przy atrybutach. Poniżej zamieszczam możliwe operatory dla DTD w HTML-u:

ZapisZnaczenie
(...)Grupowanie
AMoże wystąpić dokładnie jeden raz
A+Może wystąpić jeden lub więcej razy
A?Może wystąpić jeden raz lub nie wystąpić wcale
A*Może wystąpić zero lub więcej razy
+(A)Może wystąpić
-(A)Nie może wystąpić
A | BMusi wystąpić dokładnie jeden element: A lub B (nie oba, nie żaden, a dokładnie jeden z nich)
A , BMuszą wystąpić oba elementy A i B w dokładnie takiej kolejności
A & BMuszą wystąpić oba elementy A i B w dowolnej kolejności

Powyższa lista jest uproszczeniem stosowania pełnej składni SGML.

Rozważmy przykład:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!ELEMENT (%heading;)  - - (%inline;)* -- heading -->

Jest to deklaracja nagłówków H1, ..., H6. Makrodefinicja %heading; zostanie rozwinięta do "H1|H2|H3|H4|H5|H6". Zatem definiowanymi elementami są H1, ..., H6. Znak "|" użyty w makrodefinicji jest znakiem alternatywy, zaś nawiasy okrągłe otaczające makro (%heading;) są użyte do grupowania. Innymi słowy deklaracja określa każdy z elementów H1, ..., H6 z osobna (można ją interpretować identycznie jak sześć niezależnych deklaracji postaci <!ELEMENT H1 .... >, <!ELEMENT H2 .... >, itd.)

Jeśli chodzi o znaczniki otwierający i zamykający każdego elementu H1, ..., H6 to są one wymagane. Decyduje o tym napis "- -".

Nawiasy okrągłe (%inline;)* grupują elementy, zaś gwiazdka określa, że elementy zawarte w nawiasach mogą wystąpić dowolna liczbę razy. Zatem zapis mówi, że poprawną zawartością elementów H1, ..., H6 jest dowolna liczba, tj. zero, jeden lub więcej, napisów określonych makrodefinicją %inline;.

Kolejny przykład:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!ELEMENT UL - - (LI)+ -- unordered list -->

Definiuje on element UL. Znacznik otwierający i zamykający są obowiązkowe ("- -"), zaś poprawną zawartością jest jeden lub więcej elementów LI. Jak widzimy, znak "+" może wystąpić zarówno przed nawiasem otwierającym, jak i za nawiasem zamykającym (LI)+.

Ostatni przykład:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!ELEMENT A - - (%inline;)* -(A) -- anchor -->

Deklaracja oznacza, że element Aposiada dwa wymagane znaczniki, otwierający i zamykający. Poprawna zawartość jest zdefiniowana jako (%inline;)* -(A). Zatem może zawierać dowolna liczbę elementów typu %inline;, natomiast nie może zawierać elementu A (element A jest zawarty w zbiorze elementów %inline;). Jawne wykluczenie ma większą wagę od dołączania.

Kilka typów elementów HTML musi zawierać wykluczenia, jednym z nich jest formularz:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!ELEMENT FORM - - (%block;|SCRIPT)+ -(FORM) -- interactive form -->

Deklaracje ATTLIST#

Definicja ATTLIST ustala zbiór dopuszczalnych atrybutów elementu. Rozpoczyna się od napisu <!ATTLIST, a kończy znakiem >. Wewnątrz niej muszą zostać określone:

Krótki przykład:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!ATTLIST BR %coreattrs; -- id, class, style, title -->

Powyższe polecenie definiuje atrybuty dla elementu BR. W komentarzu zawarto nazwy możliwych atrybutów, ale żeby stwierdzić, jakie mogą przyjąć wartości należy sprawdzić makrodefinicję %coreattrs;.

Kolejny przykład:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
rowspan      NUMBER   1          -- number of rows spanned by cell --
http-equiv   NAME     #IMPLIED   -- HTTP response header name  --
id           ID       #IMPLIED   -- document-wide unique id --
valign       (top|middle|bottom|baseline) #IMPLIED
Atrybuty logiczne#

Niektóre atrybuty mogą występować w postaci logicznej (np. atrybut selected w elemencie OPTION). Ich pojawienie się w znaczniku otwierającym elementu oznacza, że wartość tego atrybutu jest "true". Ich brak oznacza wartość "false".

Logiczne atrybuty mogą legalnie przyjąć jedną wartość: nazwę samego atrybutu (np. selected="selected"). Oto przykład deklaracji takiego atrybutu:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
selected (selected) #IMPLIED -- option is pre-selected --

W HTML-u atrybut logiczny można zadeklarować następująco (pełna forma):

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<option selected="selected">
...
</option>

Możliwe jest też podanie alternatywnego zapisu (forma skrótowa):

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<option selected>
...
</option>

Typy danych w DTD#

W języku HTML stosujemy kilka podstawowych rodzajów danych. Wartość atrybutu href="" dla elementu A jest innego typu niż na przykład wartość atrybutu class="" znacznika H1.

W celu odróżnienia wartości atrybutów wprowadzono typy danych oraz pewne makrodefinicje. Oto dostępne możliwości w DTD:

Najwięcej niejasności może wystąpić przy analizie CDATA oraz #PCDATA. CDATA występuje przy określaniu większości makrodefinicji oraz atrybutów. #PCDATA występuje tylko przy deklaracji niektórych elementów (TITLE, OPTION, TEXTAREA, FIELDSET) oraz makrodefinicji (% inline).

Analizując dłużej pojęcia CDATA i #PCDATA ustaliłem, że terminy te mogą mieć inne znaczenie w przypadku DTD, a inne w przypadku XML-a. Przyznam szczerze, że dokładnej różnicy nie udało mi się wychwycić. Można powiedzieć, że CDATA oznacza zwykły test w makrodefinicji DTD, oraz zwykły tekst w atrybutach HTML. #PCDATA oznacza zwykły tekst w elementach HTML. Pisząc "zwykły tekst" mam na myśli ciąg znaków, w którym nie mogą pojawić się znaczniki HTML.

Wszystkie powyższe typy danych będą przewijały się w całym DTD. Zdefiniowano wiele makrodefinicji, których rozwinięciem jest po prostu CDATA, np: %ContentType;, %ContentTypes;, %Charset;, %Charsets;, %Character;, %LinkTypes;, %MediaDesc;, %Datetime;, %Script; oraz %Text. Zapamiętajmy zatem, że wymienione makra, w pewnym uproszczeniu, stanowią po prostu tekst nie zawierający kodu HTML.

Podsumowanie#

Tyle jeśli chodzi o budowę i interpretację poleceń w DTD. Nie będę opisywał poszczególnych makr, które grupują różne atrybuty, elementy i inne makra. To wszystko można samodzielnie odczytać i przeanalizować znając podstawy składni DTD.

Sam osobiście nigdy nie zaglądałem do definicji dokumentu - był to duży błąd. W jednym pliku mamy zapisaną całą składnię HTML-a, nie potrzeba dziesiątek książek, kursów i innych materiałów. Wystarczy nauczyć się budowy pliku, a odszukanie wymaganych atrybutów, ich wartości, dozwolonej zawartości elementów zajmuje dosłownie chwilkę.

Pasek społecznościowy

SPIS TREŚCI AKTUALNEJ STRONY

Specyfikacja (H1) DTD (H2) Podstawy (H3) Wewnętrzny DTD (H4) Zewnętrzny DTD (H4) Mieszany DTD (H4) Jednostki leksykalne DTD (H3) Komentarze (H4) Makrodefinicje ENTITY (H4) Deklaracje ELEMENT (H4) Definicja wzorca zawartości (content model) (H5) Deklaracje ATTLIST (H4) Atrybuty logiczne (H5) Typy danych w DTD (H4) Podsumowanie (H3)