Проверка правильности (валидности) построения XML-документа

Язык XML задает только общие правила, по которым создаются теги и оформляется документ XML. Эти правила изложены в спецификации XML, расположенной по адресу http:/www/w3.org/TR/REC-xml. Документ XML, написанный с учетом всех правил спецификации, называется хорошо оформ­ленным (well-formed) документом.

Подводя итоги эти правила можно кратко сформулировать правила синтаксиса языка XML:

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

2) Имя открывающего тега должно совпадать с именем закрывающего тега. Заметим, что язык XML чувствителен к регистру.

Варианты:

неправильно: правильно:
<Name></name> <name></name>

3) Элементы должны быть правильно вложены друг в друга.

Варианты:

неправильно: правильно:
<name><b> текст </name></b> <name><b> текст </b></name>

4) Имена элементов не должны содержать символа < или > и должны начинаться с буквы или символа подчеркивания. Имена элементов не могут начинаться с символов xml (в любой комбинации верхнего и нижнего регистров). В именах элементов не должно содержаться двоеточия, за исключением пространств имен.

5) Атрибуты не должны появляться более одного раза в открывающем теге или в теге пустого элемента. Значения атрибутов должны быть заключены в кавычки. В значениях атрибутов не должны содержаться прямые или непрямые ссылки на внешние сущности.

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

Хорошо оформленный документ будет гарантированно читаться и анализироваться любым XML-редактором, хотя результат анализа может оказаться совершенно неожиданным. Для того чтобы XML-редактор (XML парсер – обработчик кода) правильно проанализировал прочитанный им документ и "понял" смысл тегов, необходимо, чтобы документ не только имел правильный формат (соответствовал бы правилам синтаксиса), но и был верным (valid).

Под проверкой (validation) кода XML понимается проверка структуры документа с помощью парсера на соответствие установленным для нее правилам и определению дочерних элементов для каждого родительского элемента. Эти правила определяются в Описании типа документа (DTD) или в Схеме (XDR, XSD и др.). Для такой проверки требуется создать DTD-файл или Схему, а затем давать ссылку на файл DTD или Схемы в своих XML-файлах (в примере ссылка делается в разделе декларации файла log.XML на файл DTD с именем filename.dtd):

<!DOCTYPE log SYSTEM "filename.dtd">

Этот пример означает, что файл DTD filename.dtd с правилами описания элементов XML-файла (log.xml) находится в компьютере в каталоге SYSTEM, а не в общем каталоге PUBLIC. PUBLIC означает, что DTD- файл находится в общедоступной для всех пользователей библиотеке, в репозитории. Свои же DTD- файлы обычно хранятся отдельно, поэтому на них надо ссылаться с помощью ключевого слова SYSTEM.

Пример DTD- файла с именем filename.dtd:

<?xml version="1.0" encoding=" WINDOWS-1251"?>

<!DOCTYPE log

[

<!ELEMENT log (event)+>

<!ELEMENT event (method, ip-from, url-to, response)>

<!ELEMENT method (#PCDATA)>

<!ELEMENT ip-from (#PCDATA)>

<!ELEMENT url-to (#PCDATA)>

<!ELEMENT response (#PCDATA)>

<!ATTLIST event date CDATA #IMPLIED result CDATA #IMPLIED>

] >

Для рассмотренного DTD- файла с именем filename.dtd создан XML-файл с именем log.XML:

<?xml version="1.0" encoding=" WINDOWS-1251"?>

<!DOCTYPE log SYSTEM "filename.dtd">

<log>

<event date=" 27/May/1999:02:32:46 " result="success">

<ip-from> 195.151.62.18 </ip-from>

<method>GET</method>

<url-to> /misc/</url-to>

<response>200</response>

</event>

<event date=" 27/May/1999:02:41:47 " result="success">

<ip-from> 195.209.248.12 </ip-from>

<method>GET</method>

<url-to> /soft.htm</url-to>

<response>200</response>

</event>

</log>

Следует пояснить основные элементы DTD- файла.

DTD выглядит непривычно. Он состоит из объявлений разметки (markup declarations), начинающихся с пары символов <!. Слова ELEMENT, ATTLIST, ENTITY, NOTATION, указывают, что именно объявляется: элемент, список атрибутов, сущность или обозначение. Объявление разметки заканчивается символом ">". Каждый элемент или атрибут объявляется отдельно, поэтому все описание DTD часто бывает очень большим, иногда превышая объем описываемого XML - документа.

Рассмотрим подробнее объявление разметки каждого типа.

1) Каждый элемент документа XML должен быть описан в объявлении типа элемента (element type declaration). Объявление типа элемента начинается с символов <! ELEMENT, после которых через пробел идет имя элемента и объявляется его содержимое

Проще всего объявляется пустой элемент. Его содержимое, точнее, отсутствие содержимого, отмечается одним словом empty. Например:

<!ELEMENT br EMPTY>

После такого объявления в документе XML будет верна запись пустого элемента br в виде <br /> или в виде <br></br>

Следующее объявление можно считать полной противоположностью объявлению пустого элемента:

<!ELEMENT something ANY>

Оно означает, что элемент с именем something может содержать что угодно. Такое объявление не несет никакой информации об элементе и поэтому встречается очень редко.

Элемент с обычным текстовым содержимым и без вложенных элементов объявляется так:

<!ELEMENT name (#PCDATA)>

Слово #PCDATA (Parsed Character DATA) означает строку символов, просматриваемую программой-анализатором документа XML.

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

Например, объявление элемента sp:suppi-prod может выглядеть так:

<!ELEMENT sp:suppl-prod (sp:snum, sp:sname, sp:loc, sp:pname, sp:qty)>

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

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

<!ELEMENT someelement (#PCDATA, inelem, anoelem)>

В приведенных выше объявлениях каждый вложенный элемент может встретиться ровно один раз. То обстоятельство, что вложенный элемент можно записать в объявляемом элементе несколько раз, отмечается звездоч­кой, плюсом или вопросительным знаком.

Например, в корневой элемент sp: suppiprod можно вложить сколько угодно элементов sp:suppl-prod. Поэтому объявление корневого элемента будет выглядеть так:

<!ELEMENT sp:suppl-prod (sp:suppl-prod)* >

Звездочка после закрывающей круглой скобки означает, что список вложенных элементов может повторяться в документе XML несколько раз или не встречаться вовсе (³0). Звездочку можно поставить и после отдельного имени вложенного элемента в списке. Это будет означать повторяемость или отсутствие данного элемента в документе XML. Наконец, можно выделить скобками группу повторяющихся элементов и поставить звездочку после нее.

Есть еще два обозначения такого же рода: знак "+", означающий, что элемент или список элементов может повторяться один или несколько раз (³1), и знак "?", показывающий, что элемент или список может войти в документ не более одного раза (1 или 0).

Например, объявление элемента mymemoirs, записанное с использованием операторов повторяемости:

<!ELEMENT mymemoires (title, author, philosophizing+, sad_story*, funny_story*, lesson*, conclusion)>

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

<!ELEMENT mymemoires (title, author, philosophizing+, sad_story*, funny_story*, lesson+ | conclusion)>

В этом объявлении элемент mymemoirs может содержать один или более элементов lesson или conclusion, но не оба одновременно.

Следующий пример: объявление элемента bk:chapter:

<!ELEMENT bk:chapter (bk:title, (bk:section+, bk:listing*, bk:picture*)*, bk:conclusion?)>

Это объявление показывает, что в элемент bk:chapter сначала вкладывается один элемент bk:title, потом один или несколько элементов bk:section. Между элементами bk:section могут встречаться элементы bk:listing и bk:picture. Последним вложенным элементом может оказаться элемент bk:conclusion.

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

<!ELEMENT edition (author+, title, name,(publ-house, publ-place) | issue)) >

2) Атрибуты используются, чтобы сообщить дополнительную информацию об элементах. Атрибуты элемента объявляются уже после объявления самого элемента. Все атрибуты одного элемента объявляются сразу, одним списком. Список начинается с символов <!ATTLIST, после них через пробел следует имя элемента (например event), к которому относятся атрибуты. Затем идут объявления атрибутов (имена атрибутов: result, date, их типы: CDATA и признаки обязательности: #IMPLIED). Список, как всегда, заканчивается символом ">".

<!ATTLIST event result CDATA #IMPLIED date CDATA #IMPLIED>

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

Существует девять типов атрибутов, которые подразделяются на три категории: строковые (string), маркерные (tokenized) и перечислимые (enumerated).

Тип атрибута записывается приведенными далее обозначениями:

a) строковые (string) значения атрибутов:

cdata – любая строка символов;

b) маркерные (tokenized) атрибуты (аналоги тега А в HTML, то есть они задают перекрестную ссылку):

id – уникальный идентификатор, однозначно определяющий элемент, в котором встретился этот атрибут. Значения такого атрибута не должны повторяться в документе. В инструкции DTD только один атрибут типа ID;

idref – идентификатор, содержащий одно из значений атрибутов типа id, используется в качестве ссылки на другие элементы;

idrefs – идентификатор, содержащий набор значений атрибутов типа id, перечисленных через пробелы; тоже используется в качестве ссылки сразу на несколько элементов;

entity – имя непроверяемой анализатором сущности. Порядок использования данного атрибута будет рассмотрен в 3-ем вопросе занятия;

entities – имена непроверяемых сущностей;

nmtoken – слово, содержащее только символы, применяемые в именах, т.е. только буквы, цифры, знак подчёркивания, двоеточия, тире, точка;

nmtokens – слова, перечисленные через пробелы;

notation – обозначение.

Атрибуты типа id играют ту же роль, что и первичные ключи в таблицах баз данных. Они позволяют различать элементы и индексировать их. Это облегчает и ускоряет поиск элементов, а также позволяет ссылаться на них. Ссылки выполняются атрибутами типа idref или типа idrefs. Например, в одном месте документа могут встретиться элементы:

< name reg-num="123045">Иванов</ name >

< name reg-num="123052">Петров</ name >

с атрибутом reg-num типа id, а в другом месте – элемент:

<post reF "123045">3аведующий OTделoM</post>

с атрибутом ref типа idref. Такая связь означает, что должность Иванова – "Заведующий отделом". Объявления DTD этих элементов могут выглядеть так:

<!ELEMENT name (#PCDATA)>

<!ATTLIST name reg-num ID #REQUIRED>

<!ELEMENT post (#PCDATA)>

<!ATTLIST post ref IDREF #IMPLIED>

Значения атрибутов типа entity – это имена сущностей, объявленных в этом же описании DTD.

Атрибуты типа nmtoken могут содержать имена других элементов или атрибутов, например, для того чтобы ссылаться на них.

Значения атрибутов типа notation – это обозначения, расшифрованные в описании DTD.

c) перечислимые (enumerated) атрибуты (приводится список всех возможных значений этого атрибута):

<!ATLIST triangle angle_type (obtuse | acute | right)? #REQUIRED>

Здесь атрибут с именем angle_type для элемента, названного triangle (треугольник ), может принимать возможные значения: (obtuse - тупой или acute - острый или right - прямой) и должен всегда находиться в каждом экземпляре элемента.

Список значений перечисляемого атрибута разделяется вертикальной чертой (|) – знак ИЛИ и все значения записываются в круглых скобках.

3) Объявление атрибута заканчивается признаком обязательности присутствия атрибута в элементе или подразумеваемым значением атрибута. Такое значение, называемое значением по умолчанию, будет использовано, если атрибут не записан явно в документе XML. Признак обязательности – это одно из трех слов, показывающих, всегда ли нужно записывать атрибут и что будет, если его нет в элементе:

#required – атрибут надо обязательно записывать в элементе;

#implied – атрибут необязателен, у него нет значения по умолчанию;

#fixed – у атрибута есть только одно значение, которое записывается тут же, через пробел.

<!ATTLIST dog species #FIXED "Canis familiaris">

Здесь элемент dog имеет единственный атрибут species, значение по умолчанию которого Canis familiaris.

Если в конце объявления атрибута вместо одного из этих слов стоит значение атрибута, принимаемое по умолчанию, то понятно, что такой атрибут необязателен.

Например, атрибуты first, second и surname элемента name можно объявить следующим списком:

<!ATTLIST name

first CDATA #REQUIRED

second CDATA #IMPLIED

surname CDATA #REQUIRED>

После того как создали XML-документ и к нему DTD- файл следует проверить соответствие друг другу эти два документа. Для этого существуют программы-обработчики - парсеры – проверяющие анализаторы (validating parsers), которые входят в состав браузера (например Internet Explorer). Парсер XML проверяет правильно ли написан код на языке XML и если правильно, то он связывает с экземпляром XML документа встроенную каскадную таблицу стилей CSS (Cascading Style Sheet), а потом преобразует документ с помощью XSLT.

Вывод:

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

Наши рекомендации