5858
Введение в язык определения типов Document Type Definition (DTD)

 

Содержание.

Для чего используется DTD. go top

В спецификация XML 1.0 указывается, что логическую структуру XML-документа (подробности об XML см. в Кратком введении в XML) можно описать с помощью языка Определений Типов Документов - Document Type Definition (DTD) http://www.w3.org/TR/REC-xml#dt-doctype. В DTD используется формальная грамматика, позволяющая определить как структуру документа, так и допустимые значения. При обработке документов, если с ними будут ассоциированы правила, оформленные на языке DTD, анализаторы могут проверять данные на их соответствие с описаниями, тем самым сигнализировать о наличие структурных ошибок в данных XML-документов.

Зачем это нужно? Для упрощения программ обработки XML-документов. Так программа обработки может быть упрощена за счёт того, что она написана для работы с конкретной структурой документа, и не способной работать с множеством других различных структур. В то время как формальная проверка экземпляра конкретного документа на соответствие наперёд заданной структуре, предотвратит попаданию ошибочных данных на обработку такой программе.

Правильно оформленные документы (см. Правильно оформленные документы во Введении в XML), написанные в соответствии с неявными правилами для языка XML не способны выполнить подобный контроль данных. Ошибки в данных могут быть пропущены и тогда они приведут либо к не способности приложения выполнить работу с документом, либо могут привести к получению некорректных результатов его работы. Напротив, при наличии описания структуры на DTD при обработке документа (см. Состоятельные (или допустимые) документы во Введении в XML), его данные могут быть подвергнуты анализаторами, обеспечивающими проверку документа на допустимость, контролю на соответствие данных  грамматическим правилам, описанным в нём (см. XML-анализаторы во Введении в XML). Таким образом, если требуется эффективный контроль проверки структурных ошибок в документе, то можно воспользоваться определениями, написанными на DTD и анализатором, проверяющим документ на допустимость.

Конечно, для обработки всего одного временного документа, вы вряд ли будете разрабатывать словарь, однако при массовой обработке большого количества документов с одинаковой структуры, вам такой контроль описания этой самой структуры, скорее всего потребуется.

Ассоциирование DTD с XML-документом. go top

Определения, написанные на DTD могут быть связаны (ассоциированы) с XML-документами. Таким образом, анализаторы, проверяющие XML-документ на допустимость могут осуществить проверку корректности структуры документа по отношению к описаниям. DTD-описания могут быть внешними, внутренними или и теми и другими, т.е. смешанными. В последнем случае внутренние имеют более высокий приоритет над внешними (т.е. переопределяют последние). Связь между XML-документом и DTD-описанием осуществляется с помощью декларации DOCTYPE, помещаемой в XML-документ (см. Декларация типа документа во Введении в XML).

Декларация DOCTYPE представляет из себя тег следующей структуры:

<!DOCTYPE Name ExternalID MarkupDecl >

где

Декларации в DTD. go top

Допустимое в XML-содержание определяется следующими декларациями в DTD:

Конструкция в DTD Назначение
ELEMENT - декларации типа элемента XML
ATTLIST - декларации атрибутов, могут быть назначены конкретным элементам, а также определить разрешённые значения атрибутов
ENTITY - декларации повторно используемого содержания
NOTATION - декларации определяют внешнее содержание

ELEMENT. go top

Элемент является основным объектом языка XML, в DTD элемент объявляется с помощью тега ELEMENT и имеет следующую структуру:

<!ELEMENT Name contentspec>

где

Name - имя типа элемента. На имя типа элемента накладываются следующие ограничения, всегда применяемые к именам в XML (см. также Имена во Введении в XML): имена могут содержать буквы, цифры, двоеточия (':'), символ нижнего подчёркивания ('_'), дефис (тире или знак минуса) ('-') и точку ('.'), но не могут начинаться с цифры. Они должны начинаться только с буквы, знака подчёркивания или двоеточия. 

contentspec - определяет содержание элемента и может быть:

В последнем случае различают две модели содержания:

Формальные правила, с помощью которых определяют содержание элемента, очень похожи на те, которые используются в расширенных формах Бэкуса-Наура (Extended Backus-Naur Form - EBNF) при определении синтаксиса в языках программирования.

Определение порядка и выбор элементов go top

В таблице ниже представлены символы-разделители между элементами:

Символ Назначение
, - определяет последовательность
| - указывает на выбор одного из

При помощи первого (символ запятая ','), элементы можно объединить в последовательность, создав список элементов. Например:

        
<!ELEMENT PersonName (First, Middle, Last)> 
здесь определено, что все три элемента должны присутствовать, причём в указанном порядке. В то время как второй (символ-разделитель '|') - указывает на выбор из возможных альтернатив. Так элемент FruitBasket в определении:
        
<!ELEMENT FruitBasket (Apple | Orange)> 
может содержать одно из двух: либо Apple, либо Orange, но не обоих одновременно.

Повторяемость элементов. go top

Повторяемость элемента или группы элементов (определитель множественности или кардинальность), задаётся следующими символами:

Символ Назначение
? - не обязательный, может отсутствовать
* - ноли или больше
+ - один или больше

Отсутствие символа повторяемости указывает, что элемент должен присутствовать, причём только один раз. Символ повторяемость ставится сразу за названием элемента или сразу за закрывающей круглой скобкой группы элементов. Вот пример с использованием символов повторяемости:

        
<!ELEMENT FruitBasket (Cherry+, (Apple | Orange)*)> 

и эта группа модели содержания означает, что наша корзина может содержать один или несколько элементов Cherry, после которых следует ноль или больше экземпляров выбора между элементами Apple и Orange. Обратите внимание, что элементы Cherry должны быть расположены вместе. Ниже пример данных, удовлетворяющий такой декларации: 

        
    <FruitBasket>
    <Cherry>...</Cherry> 
    <Cherry>...</Cherry> 
    <Apple>...</Apple> 
    <Orange>...</Orange> 
    <Orange>...</Orange> 
    </FruitBasket> 

Вот ещё несколько примеров определений элементов:

        
<!ELEMENT foo (A?, ((B, C) | D), E?)> 

здесь определено, что элемент foo может содержать от одного до четырёх порождённых элементов, в зависимости от сделанного выбора, причём первым может быть  A, B или D (элемент A не обязателен), затем появляется B и C, или D, в завершении E (элемент E не обязателен).

        
<!ELEMENT foo (A, (B, C)*, D+)> 

здесь за элементом A следует ноль или больше пар B и C, а в конце по крайней мере один элемент D.

Для того, чтобы указать на смешанное содержание, в модель содержания введено ключевое слово #PCDATA. В этом случае элементы модели содержания следует разделять символом | и у группы в целом объявить множественность "ноли или больше":

        
<!ELEMENT MixedBag (#PCDATA | ItemA | ItemB)*)> 

Ниже пример данных, удовлетворяющий такому описанию:

        
    <MixedBag>
    <ItemA>...</ItemA> 
    Текст, включённый как PCDATA 
    <ItemA>...</ItemA> 
    <ItemB>...</ItemB> 
    </MixedBag> 

Нужно также иметь ввиду, что один и тот же элемент не может быть объявлен более чем один раз.

ATTLIST. go top

Атрибуты, подобны свойствам в ООП у классов, и информационно дополняют XML-элементы (см. также раздел Атрибут во Введении в XML). Объявления атрибутов DTD имеют следующую структуру:

        
<!ATTLIST ElementName AttDef* >
где ElementName - имя элемента, для которого объявляются атрибуты, а AttDef имеет следующую структуру:
        
AttDef ::=  AttName AttType DefaultDecl

здесь AttName - имя атрибута,  AttType - тип атрибута, а  DefaultDecl - значение атрибута. На имя атрибута наложены такие же ограничения, что и имя XML-элемента (см. в разделе ELEMENT данного документа, а также раздел Имена во Введении в XML).

Типы атрибутов. go top

Тип атрибута (AttType) может быть одним из следующих:

Тип Назначение
CDATA - символьные данные
ID - уникальный идентификатор
IDREF - ссылка на уникальный идентификатор
IDREFS - набор ссылок на уникальные идентификаторы
ENTITY - сущность (или замещаемое содержание)
ENTITIES - набор сущностей
NMTOKEN - именной токен 
NMTOKENS - набор именных токенов
NOTATION - один из типов нотаций
[явное перечисление] - перечисление возможных значений атрибутов

Следует сделать несколько пояснений к типам атрибутов:

Значения атрибутов. go top

DefaultDecl - определяет: как и какие значения должны быть присвоены атрибуту. В качестве значений могут быть:

Значение Назначение
#REQUIRED - атрибут должен всегда присутствовать в каждом элементе и иметь значение
#IMPLIED - атрибут является не обязательным и может отсутствовать в элементе
#FIXED + значение - определяет атрибут, всегда имеющий одно и тоже значение
значение - значение, заключённое в кавычки, определяет значение по умолчанию

Нужно иметь ввиду, что если анализатор встречает объявленный, но отсутствующий атрибут, для которого определено значение по умолчанию, то в рекомендациях предписывается, что он должен вести себя так, как будто атрибут присутствует и имеет значение по умолчанию.

Например:

        
<!ATTLIST product
 title CDATA #REQUIRED
 id ID #IMPLIED
 type NMTOKEN #REQUIRED;
 quantity CDATA "1"
 value CDATA #FIXED "дорого"
 color (серый|белый) "серый"
> 

определяет для элемента product следующие атрибуты:

Атрибут Требования к значению
title - обязательный атрибут, содержащий символьные данные
id - необязательный атрибут, который может содержать уникальный идентификатор элемента внутри документа
type - обязательный атрибут, значение которого произвольно, но обязано удовлетворять правилам имён в XML для типа NMTOKEN (например type="сыпучий")
quantity - определяет атрибут, который может и не присутствовать в элементе, в этом случае подразумевается, что его значение равно "1"
value - определяет атрибут, который всегда должен иметь значение "дорого"
color - определяет атрибут, имеющий одно из значений: "серый" или "белый", причём по умолчанию - "серый" 

ENTITY. go top

Часто используемы конструкции языка или внешние данные, могут быть предварительно объявлены как сущности, а затем использованы в документе. Имеется два вида сущностей: внутренние и внешние. 

Внутренняя сущность. go top

Внутренняя сущность используется (в том числе и в значениях атрибутов) для повторного использования одних и тех же конструкций. Так, если одна и та же конструкция используется несколько раз, то можно объявить представляющую её сущность, а затем ссылаться на последнюю везде, где возникает необходимость в конструкции (см. также раздел Ссылки во Введении в XML). Близким аналогом таких сущностей являются макроподстановки в некоторых языках программирования. Например, объявление сущности animal:

        
<!ENTITY animal "слон" >

позволяет в дальнейшем её использовать (в том числе и в атрибутах) подобно:

        
<product title="&animal;" /> <!-- здесь после подстановки сущности значение атрибута title="слон" -->  

Выше было показано объявление сущности, которая могла быть использована в любом месте XML-документа. Тем не менее, существует объявление сущностей, которые могут быть использованы только в рамках DTD-языка, например объявление элемента shape

        
<ELEMENT shape (x, y, z, R)>

после предварительного объявления сущности coords:

        
<!ENTITY % coords "x, y, z" >

может быть записано следующим образом:

        
<ELEMENT shape (%coords;, R)>

в то время как использование параметризованных сущностей в атрибутах аналогично показанному выше.

Внешняя сущность. go top

Объявление внешней сущности имеет вид:

<!ENTITY имя ExternalID NDataDecl>

здесь:

ExternalID ::= 'SYSTEM' SystemLiteral | 'PUBLIC' PubidLiteral SystemLiteral
NDataDecl ::= 'NDATA' Name

где:

Следует также отметить, что:

Рассмотрим несколько примеров, поясняющих использование внешних сущностей.

        
<!ENTITY animal SYSTEM "ent/animal.ent" >

В данном случае определена внешняя разбираемая сущность (содержимое файла animal.ent с указанным относительным его расположением) и использование ссылки на сущность &animal; в любом месте XML документа будет приводить к замене ссылки сущности на содержимое указанного файла.

        
<!ENTITY animal PUBLIC "-//ZOO//Elephant/Description" "http://enimalhost.com/animal.ent" >

Это также определение внешней разбираемой сущности, однако теперь, специализированный анализатор для зоологических XML-файлов, встретив публичную и известную ему ссылку "-//ZOO//Elephant/Description", может и не загружать определение, находящееся по адресу http://enimalhost.com/animal.ent непосредственно с сервера. Как именно в данном случае определить сущность animal - ложится на плечи анализатора. Однако в любом случае, она (сущность animal) при использовании данного объявления должна быть корректно определена.

Оба примера выше определяли внешнюю разбираемую сущность, т.е. содержимое внешнего документа было обработано XML-анализатором, при этом подразумевается, что формат данных является текстовым и содержимое его совместимо с требованиями XML. Однако, известно что имеется целый ряд двоичных форматов (например изображения), и естественно возникает законный вопрос: а как работать с подобными данными средствами XML. Возможно ли вообще такое? Чтобы ответить на этот вопрос, следует познакомиться с нотациями.

NOTATION. go top

XML-анализаторы не имеют средств по обработке двоичных файлов непосредственно. Что же делать, если мы в документе желаем использовать данные в формате двоичных файлов? Чтобы обойти эту проблему в XML используются объявления нотаций, которые позволяют связать названия форматов с внешними приложениями-обработчиками (helper application) для файлов этих форматов. Формально определение нотаций имеет вид:

<!NOTATION TypeName ExternalID>

здесь ExternalID по своей структуре полностью аналогичен тому, что и во Внешней сущности у ENTITY, т.е.:

ExternalID ::= 'SYSTEM' SystemLiteral | 'PUBLIC' PubidLiteral SystemLiteral

и определяет приложение-обработчик двоичных файлов для типа TypeName. Если в XML-документе использованы несколько различных форматов двоичных файлов (т.е. определёны как внешние сущности с применением NDATA у ENTITY), то при помощью этого определения необходимо указать соответствующие приложения-обработчики каждому из типов.  

Применяя NOTATION, имеется две возможности обработки двоичных файлов в XML.

В первом вариант требуется: 

Рассмотрим пример поясняющий это:

<!DOCTYPE menu [ 
 <!ELEMENT menu (menuitem*)>
 <!ELEMENT menuitem EMPTY>
 <!ATTLIST menuitem
  image ENTITY #REQUIRED
  title CDATA #REQUIRED
  href CDATA #REQUIRED>
 <!NOTATION gif SYSTEM "gif-viewer.exe">
 <!NOTATION jpg SYSTEM "jpg-viewer.exe">
 <!ENTITY news SYSTEM "images/news.gif" NDATA gif>
 <!ENTITY products SYSTEM "images/products.jpg" NDATA jpg>
 <!ENTITY support SYSTEM "images/support.gif" NDATA gif>
]>
<menu>
 <menuitem image="news" title="News" href="news.htm"/>
 <menuitem image="products" title="Products" href="products.htm"/>
 <menuitem image="support" title="Support" href="support.htm"/>
</menu>

Здесь атрибут image у элемента menuitem, является обязательным, и принадлежит типу ENTITY. Это означает, что должны быть объявления используемых сущностей. Действительно, имеется три объявления внешних сущностей: news, products, и support, причём все три являются не анализируемыми, т.к. у каждой из них присутствует NDATA, определяющий соответствующий тип. При этом, задействовано всего два различных типа: gif и jpg, и каждому из них определёно приложение-обработчик, используя определения NOTATION, - это gif-viewer.exe и jpg-viewer.exe, соответственно. 

Теперь рассмотрим второй вариант:

<!DOCTYPE root [ 
 <!ELEMENT root (#PCDATA)>
 <!ATTLIST root
  type NOTATION (rtf|htm|txt) #REQUIRED>
 <!NOTATION rtf SYSTEM "wordpad.exe">
 <!NOTATION htm SYSTEM "iexplore.exe">
 <!NOTATION txt SYSTEM "notepad.exe">
]>
<root type="htm">
 <![CDATA[
   <html>
    <header>
     <title>Examp</title>
    </header>
    <body>
     <!-- Здесь содержимое документа -->
    </body>
   </html>
 ]]>
</root>

Здесь через нотации определены три типа данных: rtf, htm, txt. Атрибут type элемента root указывает на формат данных, содержащихся в элементе. В данном случае это html-формат, обрабатываемый приложением iexplore.exe.

Литература go top

См. также:

 
 
Hosted by uCoz