5. Схемы данных
Схемы данных (Schemas) являются альтернативным способом создания правил построения XML-документов. По сравнению с DTD, схемы обладают более мощными средствами для определения сложных структур данных, обеспечивают более понятный способ описания грамматики языка, способны легко модернизироваться и расширяться. Безусловным достоинством схем является также то, что они позволяют описывать правила для XML-документа средствами самого же XML. Однако это не означает, что схемы могут полностью заменить DTD-описания - этот способ определения грамматики языка используется сейчас практическими всеми верифицирующими анализаторами XML и, более того, сами схемы, как обычные XML-элементы, тоже описываются DTD. Но серьезные возможности нового языка и его относительная простота, безусловно, дают основания утверждать, что будущий стандарт найдет широкое применение в качестве удобного и эффективного средства проверки корректности составления документов. В настоящее время в W3 консорциуме идет работа над первой спецификацией схем данных. Рассмотрим основные возможности схем данных, попытаемся использовать их для контроля корректности ранее описываемых XML-документов.
Внешне документы схем не отличаются от обычных документов XML. Документ размечается при помощи специальных элементов, выполняющих в схемах роль инструкций. Эти инструкции составляют набор правил, используя которые, программа-клиент будет делать вывод о том, корректен документ или нет. Схема данных, например, может выглядеть следующем образом:
<schema id="TeamSchema"><elementType id="#namee"><string/></elementType><elementType id="player"><element type="#name"/><attribute name="number"/><attribute name="type"/> </elementType><elementType id="team"><element type="#player"/><attribute name=”title”/></elementType></schema>Если мы включим приведенные правила внутрь XML-документа, программа-клиент сможет использовать их для проверки. Т.е. она теперь сможет определить, что правильным будет являться следующий фрагмент:
<team title=”Celtics”><player number="1" type=”goalkeeper”><name>John Ree</ name></ player><player number="2" type=”back”><name>Peter Loyd</ name></ player><player number="2" type=”forward”><name>Emil McGeer</ name></ player></team>Все конструкции языка схем описываются правилами "XML DTD for XML-Data-Schema".
Область схемы данных
Создавая схемы данных, мы определяем в документе специальный элемент, <schema>; внутри которого содержатся описания правил:
<schema id="OurSchema"><!-- последовательность инструкций --></schema>Если использовать отдельное пространство имен, то полный XML-документ, содержащий в себе схему данных, будет выглядеть следующим образом:
<?XML version='1.0' ?><?xml:namespace href="http://www.mrcpk.nstu.ru/schemas/" as="s"/?><s:schema id="OurSchema"><!-- последовательность инструкций --></s:schema>Описание элементов
Для определения класса элемента, к которому в дальнейшем будут применяться инструкции, описывающие его содержимое и структуру, предназначен специальный элемент схемы elementType. Название элемента задается атрибутом id . Все дальнейшие инструкции, которые относятся к описываемому классу, определяют его внутреннюю структуру и набор допустимых данных, содержатся внутри блока, заданного тэгами <elementType> и </elementType>. При определении класса элемента, можно также использовать комментарии к нему, которые заключаются в тэги <descript></descript>
Атрибуты элемента
Для того, чтобы в описании элемента определить его атрибуты и описать свойства этих атрибутов нужно использовать элемент attribute:
<elementType id="player"><attribute name="number"/>…</elementType>В данном примере элементу <player> определяется атрибут number, значением которого может быть любая последовательность разрешенных символов:
<player number="0"/><player number="some text"/>Подобно DTD, схемы данных позволяют устанавливать ограничения на значения и способ использования атрибутов. Для этого в дескрипторе <attribute> необходимо использовать параметр atttype. Например, если мы хотим указать, что значение атрибута должно использоваться программой-анализатором как уникальный идентификатор, то нам необходимо создать следующее правило:
<elementType id="player"><attribute name="number" atttype="ID"/></elementType>Если же требуется задать список возможных значений атрибута, то пример будет выглядеть следующим образом:
<attribute name="type" atttype="ENUMERATION" values="goalkeeper back halfback forward">Модель содержимого элемента
Под моделью содержимого в схеме данных понимают описание всех допустимых объектов XML-документа, использование которых внутри данного элемента является корректным. Модель содержимого определяется инструкциями, расположенными внутри блока <elementType>. Вложенные элементы описываются при помощи инструкции element, в которой параметром type указывается класс объекта - ссылка на его определение:
<elementType id="player"><element type="#name"/><element type="#nationality"/></elementType>Если требуется указать режим использования вложенного элемента, то надо определить параметр occurs:
<elementType id="player"><element type="#name" occurs="REQUIRED"/><element type="#nationality" occurs="OPTIONAL"/><element type="#clubs" occurs="ONEORMORE"/></elementType>Возможные значения этого параметра таковы:
Примеры правильных XML-документов, использующих приведенную выше схему:
<player><name>John Ree</name><nationality>English</ nationality><clubs>Celtics</clubs><clubs>Portsmut</clubs></article>или
<player><name>John Ree</name><clubs>Celtics</clubs><clubs>Portsmut</clubs></article>Кроме элементов, содержимым XML-документа могут также является обычный текст и области CDATA. Для обозначения типов содержимого текущего элемента в схемах используются следующие инструкции:
Группировка элементов
Элемент group используется для того, чтобы задать некоторую последовательность вложенных объектов:
<elementType id="team"><element type="#title" occurs="REQUIRED"/><group occurs="OPTIONAL"><element type="#player"><element type="#assistant"></group></elementType>Группировка объектов позволяет определять сразу группу объектов различных типов, которые могут находится внутри данного объекта. В приведенном примере мы указали, что внутри объекта типа conteam могут быть включены элементы title, player, и assistant, причем атрибутом occurs мы указали, что элементы в группе являются необязательными. Корректным для таких схем будут являться следующие фрагменты документов:
<team><title>Celtics</tel><player> … </player><assistant> … </assistant></team>...<team><title>Celtics</tel></team>...<team><title>Celtics</tel><player> … </player></team>При помощи атрибута groupOrder можно также задавать режим использования группированных элементов При установленном значении OR возможно использование не всех элементов группы, а лишь некоторых из них. Если задано значение AND, то оба элемента должны быть включены в обязательном порядке. Например, для следующей группы правил:
<elementType id="team"><element type="#title" occurs="REQUIRED"><group groupOrder="AND" occurs="OPTIONAL"><element type="#player"><element type="#assistant"></group></elementType>будут считаться правильными только следующие варианты:
<team><title>Celtics</tel><player> … </player><assistant> … </assistant></team>или
<team><title>Celtics</tel><player> … </player></team>Закрытая и открытая модели описания содержимого элемента
Когда мы определяем модель содержимого текущего элемента, список дополнительных допустимых элементов правилами не ограничивается - он может свободно расширяться. Например, для приведенного выше правила, кроме обозначенных элементов <title>,<player> и <assistant> вполне могут использоваться дополнительные элементы, неописанные правилами, например, <coach>:
<team><title>Celtics</tel><coach> … </coach><player> … </player><assistant> … </assistant></team>Однако в том случае, если мы хотим ограничить создаваемые нами правила от включения дополнительных элементов, мы должны использовать атрибут content и установить для него специальное значение CLOSED:
<elementType id="team" content="CLOSED"><element type="#title"><element type="#player"><element type="#assistant"></elementType>Теперь приведенный фрагмент XML-документа будет считаться некорректным, т.к. параметром content запрещено использование внутри элемента team других объектов, кроме указанных в правиле.
Иерархия классов
Для того, чтобы при описании класса ограничить список объектов, которые могут являться родительскими для данного элемента, необходимо использовать элемент схемы domain. Инструкция <domain> указывает, что текущий объект должен определяться строго внутри элемента, заданного этим тэгом. Например, в следующем фрагменте указывается, что элемент <player> может быть определен строго внутри тэга <team>: