Человеку присуща слабость всё упорядочивать и систематизировать. Заметно, что при этом становится гораздо удобнее воспринимать информацию, которая до этого казалась какой-то разрозненной и несвязанной кипой слов или цифр. Простой процесс приводит к довольно масштабному результату.
В Web-инженеринге также не обошлось без упорядочивания и систематизации. Одним из примеров подобного явления в нашей с вами области является DTD, который раскладывает по полочкам набор известных (X)HTML-тегов, не даёт запутаться валидатору и браузеру, а также помогает программисту, в некотором роде предоставляя для него минимальный набор справочного систематизированного материала. Жуть как удобно, правда?
Цели DTD
Конечно же, DTD создан не просто так. Корни данного формата уходят ещё в SGML. Можно даже сказать иначе: DTD является обязательной частью приложения SGML (коим является и HTML, к примеру). В нём объявляются и описываются всевозможные правила, применимые именно к данному языку разметки. И правда: у HTML свои правила, у XHTML уже немного другие. Даже эту разницу необходимо где-то отразить, чтобы было видно, что это не одно и то же.
Разумеется, DTD является не просто контрактом между разными программистами: DTD — это надёжная опора для валидаторов и браузеров. Да, именно DTD используют валидаторы для того, чтобы проверить документ на соответствие всем необходимым требованиям. Браузер же в меньшей степени использует данный документ.
Сформулируем основные цели, которые преследует DTD:
- Контракт между программистами;
- Описание набора правил, соответствующих для конкретного языка разметки;
- Самодокументация набора правил;
- Обособление различных приложений SGML (HTML, XHTML и так далее);
- Унификация способов записи правил разметки на разных языках.
Каждое правило тем или иным образом пересекается с другими правилами, таким образом образуя одну большую структуру данных описательного характера.
DTD в гипертекстовых языках разметки
Каждый Web-инженер встречался с таким явлением, как DOCTYPE. Все мы начинаем наши документы именно с объявления типа документа, чтобы браузеру было понятно, какой именно набор правил мы используем в разрабатываемом документе. Взглянем на различные DOCTYPE, существующие в XHTML:
Все три декларации типа документа состоят из 5 частей, каждая из которых отделена от соседних пробелами. Первые три части — DOCTYPE, html и PUBLIC — постоянны для HTML, а остальные варьируются в зависимости от используемого набора правил, применяемого к документу. Судя по данным декларациям, существуют три типа правил для HTML-документов: Strict, Transitional и Frameset. Последняя часть — это абсолютный путь (URI) к DTD-документу, который соответствует выбраному набору правил.
В данном случае, программист определяет, какой набор правил он будет использовать в разрабатываемом документе. Своё решение он выражает в виде записанного в начале HTML-файла DOCTYPE. Он,в свою очередь, будет использован браузером (User Agent) для того, чтобы выбрать соответствующий, правильный режим представления информации, более точную модель отображения данных. Можно сделать вывод, что выбор DTD является достаточно важной частью вёрстки, так как он накладывает отпечаток на последующие её этапы. Именно исходя из этого факта, можно говорить ещё и о том, что DTD является также и соглашением между Web-программистом и браузером, своеобразной гарантией правильного отображений документа.
Структура DTD
В дальнейшем мы будем рассматривать XHTML 1.0 Strict DTD.
Воспринимать структуру DTD можно достаточно просто, если помнить базовые типы данных, которые применяются в DTD. Все типы данных создаются конструкцией следующего вида:
Сейчас перечислим все возможные типы данных и остановимся на каждом из них подробно.
ENTITY
Данный тип данных используется для определения сущности, которая в дальнейшем будет подставляться в другие типы данных. Для того, чтобы лучше понять цель существования ENTITY, представьте себе константы в любом языке программирования и то, как они там используются.
Общий синтаксис ENTITY соответствует следующему выражению:
Разберём части данного выражения.
- имя — это произвольный набор символов, который, в дальнейшем, может быть использован для подстановки данной сущности;
- содержимое — это набор данных, который будет подставлен заместо имени сущности.
Для того, чтобы подставить сущность в нужную часть DTD, используется конструкция следующего вида:
Вот пример подобных конструкций:
Помимо такой записи сущностей, мы можем указать на то, что сущности находятся во внешнем файле, подключать который мы будем следующим образом:
В данной конструкции важную часть играет имя_файла, которое и указывает на тот файл, который нам следует подключить. Заметьте также после описания типа данных конструкцию %имя;, которая написана там для того, чтобы сразу подставить содержимое поключённого файла в сам DTD. Подобным образом, к примеру, описано подключение набора латинских символов:
ELEMENT
С помощью данного типа данных производится определение элемента (в нашей ситуации — HTML-элемента) и правил соблюдения иерархии для данного элемента (вложенность элементов).
Общий синтаксис ELEMENT соответствует следующему выражению:
В этом случае имя_элемента будет использоваться для записи самого элемента непосредственно в HTML-документе:
Теперь перейдём к правилам_вложенности: они могут быть записаны довольно большим количеством способов.
- EMPTY — элемент не может содержать закрывающего тега; в таком случае для закрытия тега используются конструкция />, а весь элемент принимает вид <имя_элемента />;
- (#PCDATA) или (#CDATA) — элемент может содержать только текстовое содержимое, то есть никаких вложенных тегов у него быть не может;
- (элемент1) — элемент может содержать только один указанный элемент элемент1;
- (элемент1|элемент2) — элемент может содержать либо элемент элемент1, либо элемент2, либо оба этих элемента;
- (элемент1, элемент2) — элемент должен содержать оба элемента: элемент1 и элемент2 (оба в единственном экземпляре);
- ( )+ — элемент должен содержать хотя бы один указанный элемент (или элементы);
- ( )* — элемент может содержать любое количество указанных элементов (или одного элемента), а может и не содержать их вообще;
- ( )? — элемент может содержать только один указанный элемент (или группу элементов).
Рассмотрим пример — объявление элемента html:
Данная конструкция говорит о том, что элемент html должен обязательно в себе содержать и элемент head, и элемент body. Ещё один пример, на этот раз связанный со списками:
Всё предельно понятно: элемент ol должен содержать хотя бы один вложенный элемент li.
Стоит заметить, что если вместо содержимого элемента встретится конструкция вида %имя;, то содержимое данной сущности (ENTITY) просто подставляется сюда и делается всё то же самое, что и без этой конструкции.
ATTLIST
Данный тип данных используется для определения атрибутов, которые может содержать указанный элемент.
Синтаксис определения списка атрибутов сводится к следующему виду:
Список атрибутов может быть бесконечно большим (то есть количество атрибутов для одного элемента неограничено). Чтобы было легче понять, как это работает, рассмотрим элемент с некоторыми атрибутами:
Теперь, думаю, примерно понятно, что обозначает каждая из колонок в объявлении атрибута. тип_содержимого_атрибута — это то, что может содержать в себе данный атрибут (набор символов, число, какое-то конкретное значение), а обязательность_атрибута говорит нам о том, обязателен ли данный атрибут для данного элемента. Рассмотрим значения обязательности атрибута более подробно:
- #IMPLIED — атрибут является не обязательным, но он может быть применён к данному элементу;
- #REQUIRED — атрибут должен обязательно быть записан для данного элемента;
- #FIXED 'значение' — содержимое атрибута должно быть установлено только в указанное значение.
Рассмотрим примеры. Перво-наперво, посмотрим на то, как записан элемент style и его атрибуты:
Видно, что элемент style не может содержать в себе вложенных тегов. Помимо этого, данный элемент должен обязательно содержать атрибут type, содержимое которого должно соответствовать сущности %ContentType;. Давайте найдём в файле DTD определение данной сущности:
Это значит, что данный атрибут может содержать только символьные данные (текст). Обычно, в элементе style в данном атрибуте записано text/css. Если же посмотреть на атрибут xml:space, то он может содержать только значение preserve.
Попробуем создать весь HTML-элемент:
Данный элемент является валидным сам по себе. Но посмотрим же на другое использование данного элемента:
В этом случае элемент не является валидным, так как он не соответствует указанному набору правил, а именно не содержит в себе обязательный атрибут type.
Читаем DTD
Настало время проследить за тем, как можно использовать DTD в практических целях. К примеру, с помощью него мы можем узнать, как нам следует записывать те или иные элементы XHTML.
Давайте попробуем найти все блоковые элементы с помощью DTD:
Мы видим, что это определение включает в себя два других определения. Найдём же и их:
Видим, что мы подобрались ещё ближе. Осталось найти ещё и объявленные здесь элементы — %heading;, %blocktext; и %lists; — и мы узнаем все блоковые элементы в HTML.
Давайте посмотрим на элемент h1:
Видим, что данный элемент может содержать в себе только элементы, описанные в сущности %Inline;, поэтому нам стоит найти её и все используемые в ней другие сущности:
Видим, что h1 может содержать все элементы текстового уровня, а также обычный набор символов (#PCDATA). Кроме того, отсюда сразу же можно сделать вывод о том, что данный элемент не может содержать в себе блоковые элементы: другие заголовочные элементы, параграфы, div, однако может содержать span, так как:
Здесь мы видим искомый наш элемент. Но вернёмся к нашему элементу h1. Видим в списке атрибутов лишь одну запись &attrs;, поэтому ищем запись вида <!ENTITY % attrs :
Вот оно: мы видим, что здесь используются другие группы элементов. Заметьте, что можно сразу же понять смысл определённых групп элементов: %events — это атрибуты для описания событий, %i18n — атрибуты для описания параметров интернационализации (языков, направления текста). Найдём, к примеру, последние:
Мы видим три определённых атрибута: lang, xml:lang, dir. Первые два содержат в себе описание языка, а последний может содержать только одно из двух значений: либо ltr, либо rtl.
Итоги
Многие считают, что DTD уже отживает своё. W3C продвигает новую XML Schema, которая в будуем заменит все декларации DTD. XML Schema является более органичной в том плане, что она сама написана с использованием XML и её легче обрабатывать, чем DTD. Что-ж, время покажет, но пока в интернете господствуют HTML 4, XHTML 1.0 рано хоронить DTD.
Да прибудут с вами спецификации, уважаемые читатели.