birmaga.ru
добавить свой файл

1

Создание определения типа документа (DTD)

После XML-объявления пролог документа может включать DTD, позволяющий указать типы тегов, которые может содержать ваш XML-документ. Кроме указания верифицирующему анализатору типов правильных тегов и порядка их следования DTD может указать как верифицирующему, так и неверифицирующему анализаторам место, где может находиться текст, что дает возможность анализатору определить, являются ли встреченные им пробелы значимыми, или их можно проигнорировать.

1 Основные DTD-определения


При анализе программы презентации слайдов, например, вы видели, что метод characters вызывается несколько раз перед и после комментариев и элементов slide. В том случае пробелы состояли из концов строки и табуляции, окружающих разметку. Целью такой разметки было повышение читаемости документа - пробелы никоим образом не были частью содержимого документа. Перед началом изучения DTD-определений укажем анализатору места, где пробелы нужно проигнорировать.

DTD for a simple "slide show".

-->

Затем добавьте выделенный ниже текст для указания того, что элемент slideshow содержит элементы slide и ничего более:


Как видите, DTD-тег начинается с символов , после которых следует имя тега (ELEMENT). После имени тега идет имя определяемого элемента (slideshow) и, в круглых скобках, один или более элементов, определяющих правильное содержимое для этого элемента. В данном случае запись указывает, что slideshow содержит один или более элементов slide.

Без знака плюс определение указывало бы, что slideshow состоит из одного элемента slide. В таблице 6-2 перечислены квалификаторы, которые можно добавить в определение элемента.

Таблица 6-2 Квалификаторы DTD-элемента

Квалификатор

Название

Значение


?

Знак вопроса

Необязателен (ноль или один)

*

Звездочка

Ноль или более

+

Знак плюс

Один или более

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

Вы можете также вкладывать круглые скобки для группировки нескольких элементов. Например, после определения элемента image, вы можете объявить, что каждый элемент image должен быть сгруппирован с элементом title, указав ((image, title)+). Здесь знак плюс относится к паре image/title и указывает, что может встретиться одна или более таких пар.


2 Определение текста и вложенных элементов


Теперь, когда вы указали анализатору, где не должно быть текста, укажем, где текст может быть. Добавьте выделенный ниже текст для определения элементов slide, title, item и list:

В первой добавленной строке указывается, что slide содержит элемент title, после которого идет ноль или более элементов item. Ничего нового. Следующая строка указывает, что title полностью состоит из анализируемых символьных данных (PCDATA). Они называются текстом в большинстве случаев, но в XML они называются "анализируемые символьные данные". (Это отличает их от секций CDATA, которые содержат неанализируемые символьные данные.) Знак "#" перед PCDATA указывает, что далее следует специальное слово, а не имя элемента.

В последней строке впервые встречается вертикальная линия (|), которая определяет условие "или". В данном случае может встретиться либо PCDATA, либо item. Звездочка в конце указывает, что PCDATA или item может встретиться ноль или более раз подряд. Результат такой спецификации известен под названием модели со смешанным содержимым, поскольку любое количество элементов item может быть разбросано в тексте. Такие модели должны всегда определяться следующим образом: сначала указывается #PCDATA, затем некоторое количество элементов, разделенных вертикальной линией (|), и звездочка (*) в конце.

3 Ограничения DTD


Было бы неплохо, если бы мы могли указать, что item содержит либо только текст, либо текст, за которым следует один или более элементов item. Но такой тип спецификации тяжело определить в DTD. Например, вы можете соблазниться определить item так:

Это было бы довольно точно, но как только анализатор увидит #PCDATA и вертикальную линию, он будет ожидать конец определения для соответствия модели со смешанным содержимым. Эта спецификация такой модели не соответствует, так что вы получите ошибку: Illegal mixed content model for 'item'. Foun?#x28;… (Неверная модель со смешанным содержимым для 'item'. Найден …), где шестнадцатиричный символ 28 является угловой скобкой в конце определения.

Попытка определить элемент item дважды тоже не работает. Спецификация, подобная этой:

выводит предупреждение "duplicate definition" ("двойное определение") при работе верифицирующего анализатора. Фактически, второе определение игнорируется. По-видимому, определение модели со смешанным содержимым (позволяющей элементам item быть разбросанными по тексту) является хорошим настолько, насколько мы можем его сделать.

Кроме ограничений модели со смешанным содержимым, упомянутых выше, не существует способа дальнейшей квалификации типа текста, который может встретиться там, где было указано PCDATA. Должно ли оно содержать только числа? Должно ли быть в формате даты или денежном формате? Это невозможно указать в контексте DTD.

И, наконец, отметим, что DTD не предлагает никакой иерархии. Определение элемента title одинаково относится и к заголовку элемента slide и к заголовку элемента item. При расширении DTD для разрешения HTML-разметки в дополнение к обычному тексту могло бы иметь смысл ограничение размера заголовка item по сравнению с заголовком slide, например. Но единственным способом это сделать было бы назначение одному из них другого имени, например, "item-title". Результатом отсутствия иерархии является то, что DTD заставляет вас использовать "иерархию дефисов" (или ее эквивалент) в вашем пространстве имен. Все эти ограничения являются основной движущей силой разработки стандартов спецификации схем.

4 Значения специальных элементов в DTD


Вместо указания окруженного скобками списка элементов определение элемента может использовать одно из двух специальных значений: ANY или EMPTY. Спецификация ANY обозначает, что элемент может содержать любой другой определенный элемент, или PCDATA. Эта спецификация обычно используется для корневого элемента XML-документа общего назначения, такого как, например, создаваемого в текстовом редакторе. Текстовые элементы могут встречаться в таком документе в любом порядке, поэтому имеет смысл указывать ANY.

Спецификация EMPTY означает, что элемент не имеет содержимого. То есть DTD для сообщений электронной почты, разрешающее вам "отмечать" сообщение при помощи тега , может иметь примерно такую строку:



5 Ссылка на DTD


В данном случае определение DTD расположено в отдельном файле, а не в XML-документе. Это значит, что вы должны поставить ссылку на DTD в таком документе, что сделает DTD-файл частью внешнего подмножества полного DTD для XML-файла. Как вы увидите позже, можно включить части DTD в документ. Такие определения составляют локальное подмножество DTD.


Опять DTD-тег начинается с "". В данном случае имя тега, DOCTYPE, указывает, что документом является slideshow. Это означает, что документ состоит из элемента slideshow и всего остального внутри его:


...

Этот тег определяет элемент slideshow в качестве корневого элемента документа. XML-документ должен иметь только один корневой элемент. Именно здесь указывается этот элемент. Другими словами, этот тег идентифицирует содержимое документа как slideshow.

Тег DOCTYPE располагается после XML-определения и перед корневым элементом. Идентификатор SYSTEM указывает расположение DTD-файла. Поскольку он не начинается с префикса типа http:/ или file:/, путь к расположению XML-документа является относительным. Вспомнили метод setDocumentLocator? Анализатор использует эту информацию для поиска DTD-файла, так же как делало бы ваше приложение для поиска файла относительно XML-документа. Мог бы использоваться также идентификатор PUBLIC для указания того, что DTD-файл использует уникальное имя, но анализатор должен был быть способен разрешить это имя.

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



...local subset definitions here...

]>

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


6 Определение атрибутов и сущностей в DTD


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

6.1 Определение атрибутов в DTD


Давайте определим атрибуты в программе презентации слайдов.

Добавьте выделенный ниже текст, чтобы определить атрибуты для элемента slideshow:






title CDATA #REQUIRED


date CDATA #IMPLIED

author CDATA "unknown"

>

DTD-тег ATTLIST начинает последовательность определений атрибутов. Имя, следующее после ATTLIST, указывает элемент, для которого определяются атрибуты. В данном случае таким элементом является slideshow. (Обратите еще раз внимание на отсутствие иерархии в спецификации DTD.)



Каждый атрибут определяется последовательностью из трех разделенных пробелами значений. Запятые и другие разделители не разрешены, так что форматирование определений, как показано выше, полезно для повышения читаемости. Первый элемент в каждой строке - это имя атрибута: title, date или author в данном случае. Второй элемент указывает тип данных: CDATA - это символьные данные, неанализируемые данные, в которых левая угловая скобка (>) никогда не будет истолкована как часть XML-тега. В таблице 6-3 перечислены правильные варианты для типов атрибутов.

Таблица 6-3 Типы атрибутов

Тип атрибута


Указывает…

(value1 | value2 | … )

Список значений, разделенных вертикальными линиями. (Пример находится ниже).

CDATA

"Неанализируемые символьные данные". (Для нормальных людей - текстовая строка.)

ID

Имя, которое не имеет ни один другой атрибут ID.

IDREF

Ссылка на ID, определенный где-то в документе.

IDREFS

Разделенный пробелами список, содержащий один или более ID-ссылок.

ENTITY

Имя сущности, определенной в DTD.

ENTITIES

Разделенный пробелами список сущностей.

NMTOKEN

Правильное XML-имя, состоящее из букв, цифр, дефисов, знаков подчеркивания и двоеточий.

NMTOKENS

Разделенный пробелами список имен.

NOTATION

Название DTD-определенной нотации, описывающей формат не XML-данных, таких как файлы изображений.*

* Она является быстро отживающей спецификацией, которая будет рассмотрена подробно в конце этого раздела.

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





type (tech | exec | all) #IMPLIED

>

Эта спецификация указывает, что атрибут type элемента slide должен быть записан как tye="tech", type="exec" или type="all". Другие значения неприемлемы. (Использующие DTD редакторы XML могут использовать такие спецификации для представления выпадающего списка вариантов.)


В последней записи спецификации атрибута определяется значение атрибута по умолчанию, если оно есть, и указывается, игнорируется либо нет атрибут. Таблица 6-4 показывает возможные варианты.

Таблица 6-4 Параметры спецификации атрибутов



Спецификация

Указывает…

#REQUIRED

Значение атрибута должно быть указано в документе.

#IMPLIED

Значение не должно быть указано в документе. Если оно не указано, приложение будет использовать значение по умолчанию.

"defaultValue"

Значение по умолчанию, если значение не указано в документе.

#FIXED "fixedValue"

Значение для использования. Если документ указывает любое значение, оно должно быть таким же.

6.2 Определение сущностей в DTD


До настоящего времени мы рассматривали только предопределенные сущности, например &, и вы видели, что атрибут может ссылаться на сущность. Теперь наступило время изучить, как определить свои собственные сущности.

Добавьте выделенный ниже текст в тег DOCTYPE вашего XML-файла.



]>

Имя тега ENTITY указывает, что вы определяете сущность. Далее идет имя сущности и ее определение. В данном случае вы определяете сущность с именем "product", которая будет замещать название продукта. В дальнейшем, когда название продукта изменится (что определенно произойдет), вы должны будете лишь изменить название в одном месте, и все ваши слайды будут отображать новое значение.

Последней частью является строка подстановки, которая замещает имя сущности везде, где на нее встречается ссылка в XML-документе. Строка подстановки определяется в кавычках, которые не включаются при вставке текста в документ.

Только лишь для удобства мы определили две версии: одну - для единственного числа, другую - для множественного. Так что при использовании, например, в качестве названия продукта "Wally" вы должны быть готовы ввести "Wallies" для множественного числа, и оно будет подставлено корректно.

Примечание: По правде говоря, это тип сущности, который используется главным образом во внешнем DTD. При этом все ваши документы могут обращаться к новому названию, когда оно изменится. А это только пример…

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

title="WonderWidget&product; Slide Show"

...



Wake up to <STRIKE>WonderWidgets</STRIKE><b>&products;</b>!





Overview

Why WonderWidgets&products; are

great





Who buys WonderWidgets&products;

Обратите внимание, что на созданные вами сущности ссылаются при помощи такого же синтаксиса (&entityName;), что и для предопределенных сущностей, и что на сущность можно ссылаться в значении атрибута, так же как и в содержимом элемента.


6.3 Вывод ссылок на сущность


Если вы выполните программу Echo с новой версией файла, вот что вы увидите:
ELEMENT: <p>CHARS: Wake up to <b>WonderWidgets</b>!</p> <p>END_ELM:

Обратите внимание, что название продукта было замещено ссылкой на сущность.


6.4 Дополнительные полезные сущности


Вот несколько других примеров определений сущностей, которые вы, возможно, найдете полезными при написании XML-документа:

6.5 Ссылки на внешние сущности


Также можно использовать идентификаторы SYSTEM или PUBLIC для именования сущности, определенной во внешнем файле. Сделаем это.

Добавьте выделенный ниже текст в предложение DOCTYPE вашего XML-файла для ссылки на внешнюю сущность:




<!ENTITY copyright SYSTEM "copyright.xml">

]>

Это определение обращается к информации об авторских правах, содержащейся в файле с именем copyright.xml. Создайте этот файл и запишите в него какой-то интересный текст, возможно такой:

This is the standard copyright message that our lawyers

make us put everywhere so we don'0t have to shell out a

million bucks every time someone spills hot coffee in their

lap...


И наконец, добавьте выделенный ниже текст в ваш файл slideSample.xml для ссылки на внешнюю сущность:

...






©right;

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


"http://www.example.com/servlet/CurrentDate?fmt=dd-MMM-

yyyy">

Теперь вы можете обратиться к этой сущности, так же как и к любой другой:


Today's date is ¤tDate;.

6.6 Итоговая информация по сущностям


Внешняя или внутренняя сущность, на которую есть ссылка в содержимом документа, называется сущностью общего назначения. Сущность, содержащая спецификацию DTD, на которую есть обращение из DTD, называется сущностью-параметром. (Более подробно об этом мы расскажем далее.)

Сущность, содержащая XML и являющаяся, таким образом, анализируемой, называется анализируемой сущностью. Сущность, содержащая двоичные данные (например, изображения), называется неанализируемой сущностью. (По своей природе она должна быть внешней.)


7 Обращение к двоичным сущностям

7.1 Использование типа данных MIME

Существует два способа обратиться к неанализируемой сущности, например, к файлу изображения. Первый использует механизм NOTATION спецификации DTD. Однако этот механизм является сложным, запутанным и существующим в основном для совместимости с документами SGML. Мы будем иметь возможность рассмотреть его более детально при обсуждении DTDHandler API, а сейчас достаточно сказать, что комбинация недавно определенного стандарта пространства имен XML и типов данных MIME, определенных для вложений электронных сообщений, обеспечивает намного более полезный, понятный и расширяемый механизм для обращения к неанализируемым внешним сущностям.

Добавьте выделенный ниже текст в ваш файл slideshow.dtd для настройки программы slideshow на использование файлов изображений:

type (tech | exec | all) #IMPLIED

>

<!ELEMENT image EMPTY>



<!ATTLIST image

alt CDATA #IMPLIED

src CDATA #REQUIRED

type CDATA "image/gif"

>

Эти изменения определяют image как необязательный элемент в slide, определяют его как пустой элемент и определяют необходимые для него атрибуты. Тег image похож на тег img HTML 4.0 с дополнением спецификатора типа изображения type. (Тег img определен в спецификации HTML 4.0.)


Атрибуты тега image определяются в записи ATTLIST. Атрибут alt, определяющий альтернативный текст для отображения при неудачном поиске изображения, принимает символьные данные (CDATA). Он имеет "предполагаемое" значение, то есть является необязательным, и программа, обрабатывающая данные, знает достаточно, чтобы заместить его чем-то вроде "image not found" ("изображение не найдено"). С другой стороны, атрибут src, который содержит имя изображения для вывода, является необходимым.

Атрибут type предназначен для спецификации типа данных MIME, как определено в ftp://ftp.isi.edu/in-notes/iana/assignments/mediatypes/. Он имеет значение по умолчанию: image/gif.

Примечание: Отсюда понятно, что символьные данные (CDATA), используемые для атрибута type, должны быть одним из MIME-типов данных. Двумя наиболее общими форматами являются: image/gif и image/jpeg. Основываясь на этом, хорошо было бы указать список атрибутов в этом месте, используя что-либо наподобие: type("image/gif", "image/jpeg"). Однако это работать не будет. Прямой слеш не является частью установленного набора символов для меток имени, поэтому такое объявление является ошибочным. Кроме того, создание списка атрибутов в DTD ограничило бы доступные MIME-типы до определенных на сегодняшний день. Использование же CDATA оставляет вопрос открытым, то есть объявление будет продолжать оставаться правильным и при определении дополнительных типов.

В документе ссылка на изображение с именем "intro-pic" может выглядеть примерно так:


Intro Pictype="image/gif" />


7.2 Альтернатива: использование ссылок на сущность


Использование типов данных MIME в качестве атрибута элемента является гибким и расширяемым механизмом. Для создания ссылки на внешнюю сущность ENTITY с использованием механизма нотаций вам необходимы элементы DTD NOTATION для данных jpeg и gif. Они, конечно, могут быть получены из какого-нибудь центрального хранилища. Но в дальнейшем вам нужно было бы определить отдельный элемент ENTITY для каждого изображения, к которому вы хотели бы обратиться! Другими словами, добавление нового изображения к вашему документу всегда бы требовало определения новой сущности в DTD и ссылки на нее в документе. Принимая во внимание повсеместность спецификации HTML 4.0, более новый стандарт должен использовать типы данных MIME и объявление подобное image, которое предполагает, что приложение знает, как обрабатывать такие элементы.