Границы моего языка означают границы моего мира.
Людвиг Витгенштейн, философ
Мы выбираем язык не потому, что он кажется нам необходимым, — мы выбираем себе язык и тем самым делаем его необходимым.
Ролан Барт, литературовед
Вряд ли сегодня среди людей, регулярно пользующихся компьютером и Интернетом, найдется кто-то, кто никогда не слышал об XML.
Как и HTML, он появился на свет в качестве языка теговой разметки. Сегодня XML стал играть роль универсального формата для хранения информации о любых иерархических объектах и для обмена этой информацией между удаленными приложениями, работающими на любых платформах.
Средства по грамматическому разбору XML сегодня включены практически во все популярные языки программирования, а сфера его применения настолько разрослась и стала такой многогранной, что в настоящее время правильнее будет говорить об XML-технологиях, чем о простом языке разметки.
Зачем нам понадобился XML...
На основе XML построены конфигурационные файлы некоторых игр, например «Демиургов», и некоторых программ, например Skype. Обладая должными знаниями, можно их «тонко» настроить под собственные нужды.
На основе XML создана технология AJAX, работающая в таких популярных проектах, как поисковик Google или система блогов Livejournal.
На основе XML основан actionscript большинства flash-игр, язык разметки xhtml, с его применением можно настроить удобный обмен информацией между браузером и сервером.
...и что он собой представляет?
XML — это английская аббревиатура от extensible markup language, означающая в переводе «расширяемый язык разметки».
Это важно: языки разметки не имеют ничего общего с языками программирования. Они служат лишь для описания и структурирования информации.
Вначале такие языки использовались для разметки текстовой информации при подготовке ее к публикации. Классическим примером языка разметки является HTML (Hypertext Markup Language). С помощью этого языка размечены страницы, которые отображаются в нашем браузере, когда мы знакомимся с содержимым сайта. Так, например, строка
Этот текст содержит <B>жирный</B> шрифт и <I>курсив</I>.
будет представлена в браузере в виде:
Этот текст содержит жирный шрифт и курсив.
Здесь используется пара тегов: открывающий <B> и закрывающий </B> окаймляют часть текста, которая должна быть выведена жирным шрифтом. «B» — первая буква английского слова «Bold» — «яркий». Другая пара тегов, открывающий <I> и закрывающий </I>, окаймляет часть текста, которая должна быть выведена курсивом, ведь «I» — первая буква английского слова «Italic». Во многих европейских странах курсив называют «итальянским» стилем шрифта. Обратите внимание, что каждый HTML-тег заключен в угловые скобки, а отличительным признаком завершающего тега является прямая наклонная черта /.
Даже на этом простом примере видны те недостатки HTML-формата, которые и привели к появлению стандарта XML. Главные из них — следующие.
HTML — язык заранее определенных тегов, за каждым из которых стандартом закреплена определенная роль. Набор этих тегов громоздок и при этом нерасширяем.
HTML предназначен для визуализации передаваемой информации и не имеет достаточных средств для описания сущности этой информации.
Так, например, если бы на сайте журнала «Лучших компьютерных игр» была помещена статья Васи Пупкина об играх для малышей, то было бы логично иметь в ее исходном тексте такие теги, как AUTHOR (автор), TITLE (статья), THEME (тема) и AUDIENCE (аудитория, для которой статья предназначена):
<AUTHOR>Василий Пупкин</AUTHOR>
<TITLE>Онлайновые игры для малышей</TITLE>
<AUDIENCE>малыши</AUDIENCE>
<THEME>онлайновые игры</THEME>
Нужно ли говорить, насколько такая возможность наращивания тегов облегчила бы работу поисковым программам-паукам по индексации сайта и браузерам — по его визуализации?
Предыстория языка ведет свое начало с 60-х годов прошлого века, когда в IBM были начаты работы по созданию простой и универсальной технологии по платформонезависимому описанию и обмену документами. Это привело к созданию обобщенного языка разметки GML (аббревиатура от «Generalized Markup Language»).
В 1986 году Международная организация стандартизации ISO (International Organization for Standardization) выпустила стандарт GML, известный как SGML (Standard GML). Главной проблемой SGML считается его сложность и громоздкость. Это и привело к появлению на свет таких потомков этого языка разметки, как HTML и XML.
История XML начинается в 1996 году, когда встал вопрос о создании такого подмножества языка разметки, которое было бы пригодно и для обмена между веб-клиентами и веб-серверами, и для описания издательских документов. Первая спецификация языка увидела свет в ноябре 1996 года. В январе 1997 года появился первый XML-анализатор. С марта 1997 года начали появляться первые XML-приложения. Осенью того же года поддержку XML реализовал браузер Internet Explorer.
И наконец, в феврале 1998 года была опубликована рекомендация XML 1.0. С тех пор рост и поддержка языка происходят нарастающими темпами и охватывают все более широкие сферы применения.
Несмотря на богатые возможности, язык HTML со своим ограниченным и строго детерминированным словарем стал со временем напоминать язык племени мумбо-юмбо. С одной стороны, явный дефицит слов. С другой стороны, отсутствует механизм мобильного их наращивания. На фоне этих проблем сравнительно недавно, в 1996 г., возник язык разметки XML. Хоть он и не является прямым потомком HTML, но максимально походит на него по синтаксису, и при этом предназначен для хранения и передачи объектов информации, концентрируясь на сущности этой информации, а не на ее визуальном представлении.
Это важно: главное свойство языка XML — его способность к наращиванию (eXtensible), что означает возможность вводить новые теги, публиковать правила их использования и тем самым создавать новые реализации языка XML.
Такие реализации в последнее время стали все чаще называть XML-словарями.
Устройство ХМL и создание XML-словаря
Чтобы проще было ввести в курс дела читателей, знающих об XML лишь понаслышке, я начну с простых примеров. Попробуем прямо сейчас создать собственное расширение XML. Стандарт предоставляет нам для этого немалую свободу. Однако, как и любая свобода, она ограничена забором из запретов, которые и составляют сущность стандарта XML. Я буду рассказывать о них постепенно, по ходу разбора примеров.
Допустим, мы хотим создать свое собственное расширение XML (или XML-словарь), которое описывает шахматную позицию. Начнем с небольшой заготовки:
<?xml version="1.0" encoding="UTF-8"?>
<POSITION>
</POSITION>
Элементы и атрибуты
Даже на основе этой «пустышки» можно сделать немало выводов об устройстве XML-языка. Прежде всего, XML представляет собой простой текстовый файл, легко читаемый как машиной, так и человеком. В первой (заголовочной) строке указывается, что создаваемый файл будет соответствовать стандарту XML версии 1.0 и что для текстовой информации будет использоваться одна из самых универсальных и потому популярных сегодня в Интернете кодировок — UTF-8. Версия и кодировка заданы с помощью атрибутов version и encoding, аналогичных тем, что применяются в языке разметки HTML. Подробнее формат атрибутов мы обсудим ниже. Сейчас замечу лишь, что в заголовочной строке XML-файла атрибут кодировки encoding не является обязательным. При его отсутствии используется кодировка, принятая по умолчанию, то есть все та же UTF-8. Если вы намерены обмениваться XML-файлами лишь между компьютерами с операционной системой Windows и не планируете включать в эти файлы китайские иероглифы или немецкие буквы с умлаутами, то ничто не мешает вам установить русскую кодировку, принятую в Windows:
<?xml version="1.0" encoding="Windows-1251"?>
Пара тегов <POSITION> и </POSITION>, с которых начнется иерархическое построение нашей шахматной позиции, определяет здесь корневой элемент. Следует всегда помнить, что корневой элемент в любом XML-документе должен встречаться ровно один раз. XML-документ, таким образом, напоминает дерево, у которого ровно один ствол, от которого могут произвольным образом ветвиться отростки — дочерние элементы.
Что же такое элемент XML? С точки зрения синтаксиса языка — это пара из открывающего и закрывающего тегов и всего того, что между ними заключено. Элемент может иметь значение, атрибуты и содержать в себе другие элементы. Так, например, в строке <LETTER font=«Currier» size=«12»>альфа</LETTER> элемент LETTER имеет значение «альфа» и два атрибута: font со значением «Currier» и size со значением 12. Атрибуты, как видно из данного примера, определяются всегда в открывающем теге и отделяются друг от друга пробелами. Формат их прост: название, знак равенства и в кавычках (одинарных или двойных) — значение.
Это важно: в языке XML, в отличие от более терпимого HTML, каждый начинающий тег обязательно должен сопровождаться тегом завершающим.
Как и в HTML, пары тегов не должны перехлестываться. Это означает, что конструкция типа <A><B> </B></A> допустима (элемент B здесь является составной частью элемента A), а конструкция <A><B></A></B> — запрещена стандартом. Язык XML допускает для пустого элемента вместо пары тегов <A> </A> использовать одиночный тег <A/> с наклонной чертой у конечной, а не начальной угловой скобки. Например, пустую шахматную позицию, доску без фигур, мы могли бы изобразить так:
<?xml version="1.0" encoding="UTF-8"?>
<POSITION/>
Это важно: XML чувствителен к регистру букв в именах элементов и атрибутов.
Так, элементы POSITION и position будут восприниматься языком как различные! Этим язык XML существенно отличается от HTML.
XML-cловарь шахматных позиций, первая версия
Попробуем теперь описать реальную позицию. Для определенности я возьму задачу-двухходовку Д. Шумера, опубликованную впервые в «Transvaal Leader» в 1906, и попытаюсь сконструировать XML-файл, ее описывающий.
<?xml version="1.0" encoding="UTF-8"?>
<!-- Описание шахматной позиции -->
<POSITION>
<!-- Общие сведения -->
<AUTHOR>Д. Шумер</AUTHOR>
<SOURCE>Transvaal Leader, 1906</SOURCE>
<NOTE>Задача-двухходовка</NOTE>
<!-- Шахматные фигуры -->
<FIGURE>
<NAME>Король</NAME>
<COLOR>Черный</COLOR>
<PLACE>b8</PLACE>
</FIGURE>
<FIGURE>
<NAME>Король</NAME>
<COLOR>Белый</COLOR>
<PLACE>d6</PLACE>
</FIGURE>
<FIGURE>
<NAME>Ферзь</NAME>
<COLOR>Белый</COLOR>
<PLACE>h1</PLACE>
</FIGURE>
<FIGURE>
<NAME>Слон</NAME>
<COLOR>Белый</COLOR>
<PLACE>g4</PLACE>
</FIGURE>
</POSITION>
Разберем теперь созданный нами XML-словарь для описания шахматных позиций. В данном формате используются необязательные элементы AUTHOR, SOURCE и NOTE для указания автора позиции, ее источника и краткого пояснения соответственно. Затем следует множество элементов FIGURE, каждый из которых описывает отдельную фигуру или пешку. На количество элементов FIGURE мы не накладываем здесь никаких ограничений. Каждый из этих элементов содержит в себе 3 вложенных элемента: NAME, COLOR и PLACE, описывающие соответственно название фигуры, ее цвет и положение на шахматной доске. Например, составной элемент <FIGURE> ... </FIGURE> описывает черного короля на поле b8. Обратите внимание, что каждый из этих трех элементов используется в элементе FIGURE ровно один раз. В самом деле, бессмысленным будет описание фигуры, название, цвет или позиция которой не оговорены вообще или определены дважды.
Строка <!-- Описание шахматной позиции --> и другие аналогичные строки являются комментариями. В отличие от элемента NOTE, они не являются частью информации, передаваемой XML-форматом. Такие комментарии игнорируются всеми XML-анализаторами и нужны только разработчикам и людям, которые будут просматривать XML-файл глазами. Этим они напоминают комментарии, используемые в языках программирования.
Итак, используя общие принципы построения XML, определяющие лишь правила построения элементов, мы практически создали свой специализированный XML-словарь со своими, только этому словарю присущими элементами и со своими особыми правилами. Этим форматом теперь можно пользоваться для обмена шахматными позициями между различными приложениями. Это может понадобиться и для онлайновой игры в шахматы, и для заполнения какой-нибудь шахматной базы данных. Программисты смогут на основе наших правил произвести грамматический разбор (parsing) нашего файла и при необходимости представить его в виде, привычном для шахматистов (тестовая нотация, диаграмма).
Достоинства и недостатки XML
Из нашего описания видны как достоинства, так и недостатки XML-стандарта. Достоинством является легкость восприятия такого описания. Его легко можно проанализировать даже без комментариев, легко исправить вручную. Так как формат текстовый, то он практически не зависит от платформы, на которой будет использован. Кодировка символьных строк, чисел и дат в нем оговорена заранее. Еще одним достоинством является иерархический характер описания информации. Это делает формат практически универсальным.
Недостатки вытекают все из того же текстового представления. Файлы имеют большой размер. Теговая разметка делает их особенно «рыхлыми». При представлении очень большого объема информации возникнут сложности с быстрым доступом к отдельным элементам, так как для анализа файла все содержимое придется помещать в оперативную память компьютера.
XML-cловарь шахматных позиций, вторая версия
Что касается «рыхлости» представления информации, то ее в данном случае можно снизить, используя атрибуты, а не элементы для описания названия, цвета и положения шахматных фигур. Создадим альтернативный XML-словарь следующим образом:
<?xml version="1.0" encoding="UTF-8"?>
<POSITION>
<!-- Общие сведения -->
<AUTHOR>Д. Шумер</AUTHOR>
<SOURCE> Transvaal Leader, 1906</SOURCE>
<NOTE>Задача-двухходовка</NOTE>
<!-- Шахматные фигуры -->
<FIGURE name="Король" color="Черный" place="b8" />
<FIGURE name="Король" color="Белый" place="d6" />
<FIGURE name="Ферзь" color="Белый" place="h1" />
<FIGURE name="Слон" color="Белый" place="g4" />
</POSITION >
Здесь, как и в первом варианте XML-словаря, каждая фигура описывается элементом FIGURE, однако теперь этот элемент не обладает ни значением, ни вложенными элементами (потому он и представлен одинарным тегом с завершающей наклонной чертой <FIGURE />). Вложенные элементы заменили 3 атрибута, определяющие те же самые характеристики: name (наименование), color (цвет) и place (местоположение на шахматной доске).
Устанавливаем правила
Строго говоря, созданные нами два варианта XML-форматов для описания шахматных позиций XML-словарями пока не являются. Это лишь примеры того, как эти словари должны быть организованы. Мы как бы построили XML-словари в своей голове. Мы придумали структуру, или набор правил, которые должны соблюдаться. Теперь нам осталось добиться, чтобы их поняли и другие люди, которые будут присылать нам данные в одном из этих форматов и которые будут писать программы для их грамматического разбора.
DTD, или декларация
Как же оформить правила нашего языка? Существуют различные способы. Один из них — это определение типа документа, или DTD (аббревиатура от английского «document type definition»). На русском языке это описание часто называют декларацией. Для простоты изложения я создам сначала DTD-описание для каждого из наших словарей, а затем объясню, что означают строки этой записи.
Для первой версии словаря файл DTD будет выглядеть так:
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT POSITION (AUTHOR?, SOURCE?, NOTE*, FIGURE*)>
<!ELEMENT AUTHOR (#PCDATA)>
<!ELEMENT SOURCE (#PCDATA)>
<!ELEMENT NOTE (#PCDATA)>
<!ELEMENT FIGURE (NAME, COLOR, PLACE)>
<!ELEMENT NAME (#PCDATA)>
<!ELEMENT COLOR (#PCDATA)>
<!ELEMENT PLACE (#PCDATA)>
Строка <!ELEMENT POSITION (AUTHOR?, SOURCE?, NOTE*, FIGURE*)> означает, что элемент POSITION является составным и включает в себя элементы AUTHOR, SOURCE, NOTE и FIGURE. Символ-суффикс (*) после элементов FIGURE и NOTE означает, что эти элементы могут встречаться в рамках элемента POSITION сколько угодно раз, в том числе и ни разу не встречаться. Полное отсутствие элементов FIGURE соответствует пустой шахматной позиции. Знак (+) после элемента (у нас он не был использован) позволяет элементу появляться один или более раз. Если бы мы захотели запретить изображать пустые позиции в нашем XML-формате, нам следовало бы поставить FIGURE+ вместо FIGURE*. Знак (?) после элементов AUTHOR и SOURCE разрешает использование этих элементов 0 или 1 раз. И, наконец, отсутствие знака означает использование элемента ровно один раз. Такую ситуацию мы описали в строке <!ELEMENT FIGURE (NAME, COLOR, PLACE)>
Она оговаривает, что каждый элемент FIGURE должен обязательно содержать элементы NAME, COLOR и PLACE, причем каждый из них ровно один раз.
Если кто-нибудь из читающих данную статью использовал когда-нибудь регулярные выражения (особенно часто они используются при написании серверных веб-скриптов на языках Perl или PHP), он воспримет такое использование символов-суффиксов как нечто знакомое и естественное. В регулярных выражениях эти знаки используются в том же смысле, хотя и в ином контексте.
Строка <!ELEMENT NAME (#PCDATA)> означает, что элемент NAME содержит в себе некое грамматически разбираемое (в соответствии с теговой структурой) символьное значение. Английская аббревиатура PCDATA (сокращение от «parsed character data») именно это в переводе и означает.
Так что если вы собираетесь помещать в это поле простое символьное значение, позаботьтесь о том, чтобы оно не содержало зарезервированных символов «<», «>» и «&». Эти знаки должны быть заменены на «<», «>», «&» соответственно. Если в тексте встречаются двойные или одинарные кавычки, то их также во избежание неправильного толкования следует заменить на «"» и «'» соответственно.
Для второго варианта XML-словаря, в котором центр тяжести информации перенесен с элементов на атрибуты, DTD-описание будет выглядеть следующим образом:
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT POSITION (AUTHOR?, SOURCE?, NOTE*, FIGURE*)>
<!ELEMENT AUTHOR (#PCDATA)>
<!ELEMENT SOURCE (#PCDATA)>
<!ELEMENT NOTE (#PCDATA)>
<!ELEMENT FIGURE EMPTY>
<!ATTLIST FIGURE
color (Черный|Белый) #REQUIRED
name (Король|Ферзь|Ладья|Слон|Конь|Пешка) #REQUIRED
place (CDATA) #REQUIRED
>
Чем отличается это описание от предыдущего? Во-первых, обратите внимание на указание EMPTY (пустой) для элемента FIGURE, так как этот элемент во втором варианте словаря не имеет ни значения, ни внутренней структуры. Блок <!ATTLIST FIGURE... > описывает атрибуты этого элемента. Тип CDATA означает простой символьный тип в отличие от грамматически разбираемого символьного типа PCDATA. Практически это означает, что здесь снимается запрет на употребление угловых скобок и знака апострофа. Путаницы не возникает, так как атрибут окаймляется кавычками. Суффикс #REQUIRED (в переводе с английского — «затребован») оговаривает обязательность указанного атрибута в данном элементе. Для атрибута color значение ограничено двумя вариантами («Черный» и «Белый»). Такие перечисляемые варианты значений должны разделяться вертикальной чертой (символ «|»). Атрибут name имеет аналогичное перечисляемое описание. Это позволяет исключить использование недопустимых наименований шахматных фигур.
Как связать XML-документ со своей DTD-декларацией?
Возникает вопрос: как же теперь установить связь между самим XML-файлом и его DTD-описанием. Существует два способа связывания: внутренний и внешний.
При внутреннем связывании создается специальный декларативный элемент DOCTYPE для корневого элемента POSITION нашего XML-документа, который включает в себя все остальные декларативные элементы. Этот текст внедряется затем в XML-файл сразу после строки-заголовка. Выглядит это так:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE POSITION[
<!ELEMENT POSITION (AUTHOR?, SOURCE?, NOTE*, FIGURE*)>
<!ELEMENT AUTHOR (#PCDATA)>
......................................
......................................
]>
<POSITION>
.......................................
.......................................
</POSITION >
При внешнем связывании DTD-декларация XML-документа выкладывается в отдельный файл. Допустим, мы дали XML-файлу имя: chess.xml, а его описанию — имя chess.dtd. Для этого способа связывания также следует включить декларативный элемент DOCTYPE сразу после заголовочной строки. Однако теперь он не содержит в себе все остальные декларативные элементы, а лишь ссылается на тот внешний файл chess.dtd, который их содержит. Выглядит это так:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE POSITION SYSTEM "сhess.dtd">
<POSITION>
.......................................
.......................................
</POSITION >
Такое связывание предполагает, что файл сhess.dtd всегда следует искать в том же самом каталоге, что и файл chess.xml. Это простой подход, однако его никак не назовешь удобным. Ведь DTD-описание мы создаем один раз, а создавать соответствующие ему XML-файлы будем многократно. Зачем же каждый раз пересылать их вместе? Удобнее всего поместить декларацию где-нибудь в общедоступном месте, на которое дать ссылку (URL — universal resource locator). Например, если мы выложим файл chess.dtd на сайте журнала «Лучшие компьютерные игры» (www.lki.ru) в каталоге chess, то строка, обеспечивающая внешнюю связь XML-файлов со своим DTD-описанием, будет выглядеть так:
<!DOCTYPE POSITION SYSTEM "http://www.lki.ru/ToolBar/0809/XML/сhess.dtd">
Такой подход имеет массу преимуществ. Кто бы и где бы ни использовал теперь файлы созданного нами словаря для обмена шахматными позициями, он всегда получит доступ к его описанию. А получив это описание, сможет и проверить правильность синтаксиса при формировании XML-файлов, и организовать их правильный грамматический разбор.
XSD, или XML-схема
Определение DTD-декларации — не единственный способ описания правил, по которым строится структура XML-словаря. Сегодня все более популярным становится другой способ — XML-схема, или XSD (аббревиатура от XML Schema Defenition — «определение XML-схемы»). Он более сложен для популярного изложения, однако построен более логично и имеет массу преимуществ по сравнению с деклараций:
дает намного больше возможностей;
поддерживает пространство имен и типизацию данных (ниже это будет объяснено);
сам основан на XML-формате, а потому расширяем и легко грамматически разбираем.
Существуют различные способы или технологии построения XSD-схемы. Не будучи в состоянии все их охватить в небольшой статье, я буду пользоваться той, которая мне ближе и которую я использую в ходе своей повседневной программистской работы.
Начнем строить схему нашего первого варианта XML-словаря для описания шахматных позиций. Вначале, как обычно, создадим небольшую заготовку.
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="POSITION" type="TypePosition" />
..................
</xsd:schema>
Первая строка этого документа не нуждается в комментировании. Ею начинается любой XML-документ. А создаваемая нами схема, как уже говорилось выше, представляет собой одну из XML-реализаций. Однако XSD — это не произвольный XML-документ, а вполне конкретный XML-словарь, имеющий свои строго оговоренные имена элементов и правила. Одна из его отличительных черт — это наличие корневого элемента schema. Он определен во второй строке нашей заготовки:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
Внимательный читатель заметит, что имя корневого элемента schema наш файл мог получить и случайно. Мало ли кто как назовет корневой элемент своего словаря? Где гарантия, что кто-нибудь не назовет его точно так же — schema? Однако обратите внимание на префикс xsd (отделен двоеточием) при элементе schema и на атрибут xmlns, этот префикс определяющий. Когда в одном XML-формате упоминаются имена элементов двух различных XML-словарей (в нашем случае это XSD и наш словарь шахматных позиций), их имена могут, конечно, случайно пересечься. Чтобы их при этом можно было гарантированно различать, в XML введено понятие пространства имен. Для каждого пространства с помощью атрибута xmlns элемента schema и вводится специальный префикс такого пространства (собственно, xmlns — это аббревиатура от «XML Name Space» — «пространство имен XML»). В нашем случае xsd.schema однозначно говорит о том, что элемент schema принадлежит пространству имен XSD, за которым закреплен идентификатор «http://www.w3.org/2001/XMLSchema».
Третья строка нашей заготовки определяет корневой элемент POSITION нашего XML-словаря. Он вводится с помощью элемента xsd:element из пространства имен XSD. Его атрибут name определяет имя нашего корневого элемента — POSITION, а атрибут type — его тип TypePosition, название которого мы придумали сами и который опишем ниже с помощью специального XSD-элемента complexType (в переводе — «составной тип»):
<xsd:complexType name="TypePosition">
<xsd:sequence>
<xsd:element name="AUTHOR" type="xsd:string" minOccurs="0" />
<xsd:element name="SOURCE" type="xsd:string" minOccurs="0" />
<xsd:element name="NOTE" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="FIGURE" type="TypeFigure" minOccurs="0" maxOccurs="32" />
</xsd:sequence>
</xsd:complexType>
Как видите, придуманный нами новый тип данных TypePosition состоит из последовательности элементов AUTHOR, SOURCE, NOTE и FIGURE. Для этого они и помещены в специальный XSD-элемент — sequence (в переводе — «последовательность»). Каждый из наших элементов определен с помощью XSD-элемента element. Для каждого указано минимальное и максимальное число раз, которое он может встречаться в последовательности. Для этого служат необязательные атрибуты minOccurs и maxOccurs. По умолчанию их значения равны 1. Так, например, элемент AUTHOR при описании шахматной позиции может встретиться не более 1 раза (отсутствующий атрибут maxOccur принимается за 1), но может и вообще не встретиться (minOccurs=«0»). Элемент NOTE может при описании позиции использоваться сколько угодно раз. Значение maxOccur=«unbounded» означает бесконечность (в переводе — «неограниченный»). Для элемента FIGURE введено ограничение сверху — 32. Хочу обратить внимание, что при определении DTD-декларации такой уровень точности при описании был бы невозможен.
Вернемся к описанию придуманного нами типа TypePosition. Элементы определены как строчные (атрибут type=«xsd:string»), а элемент FIGURE имеет собственный тип — TypeFigure, который в первом приближении может быть нами описан следующим образом:
<xsd:complexType name="TypeFigure">
<xsd:sequence>
<xsd:element name="NAME" type="xsd:string"/>
<xsd:element name="COLOR" type="xsd:string"/>
<xsd:element name="PLACE" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
Думаю, данная запись уже не нуждается в пояснении. Все в этой конструкции нам уже знакомо. Цвет фигур и их названия описаны здесь простыми строками, однако они могут быть ограничены фиксированным набором значений. Заменим строчный тип string в описании элементов NAME и COLOR на наши пользовательские — TypeName, TypeColor:
<xsd:sequence>
<xsd:element name="NAME" type="TypeName"/>
<xsd:element name="COLOR" type="TypeColor"/>
</xsd:sequence>
Тип TypeColor опишем ниже:
<xs:simpleType name="TypeColor">
<xs:restriction base="xs:string">
<xs:enumeration value="Белый" />
<xs:enumeration value="Чёрный" />
</xs:restriction>
</xs:simpleType>
Этот тип, в отличие от FigureType, не является контейнером из последовательности различных элементов. Поэтому он относится к простым типам (simpleType) и является лишь ограничением на уже существующий строчный тип. Строка остается строкой, однако теперь ее значения ограничены заранее перечисляемым набором. Названия XSD-элементов restriction (в переводе — «ограничение») и enumeration («перечисление») именно это и отражают. А атрибут base элемента restriction указывает на тот базовый тип, который подвергается ограничениям, — string. Из простых базовых типов, используемых особенно часто, читателю следует также знать: int (целые числа), decimal (действительные числа), date (дата). В нашем шахматном примере они не использованы.
Тип TypeName, ограничивающий название шахматной фигуры фиксированным перечнем строк, определяется аналогично. А теперь соберем нашу XSD-схему в одно целое:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="POSITION" type="TypePosition" />
<xsd:complexType name="TypePosition">
<xsd:sequence>
<xsd:element name="AUTHOR" type="xsd:string" minOccurs="0" />
<xsd:element name="SOURCE" type="xsd:string" minOccurs="0" />
<xsd:element name="NOTE" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="FIGURE" type="TypeFigure" minOccurs="0" maxOccurs="32" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TypeFigure">
<xsd:sequence>
<xsd:element name="NAME" type="TypeName"/>
<xsd:element name="COLOR" type="TypeColor"/>
<xsd:element name="PLACE" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xs:simpleType name="TypeName">
<xs:restriction base="xs:string">
<xs:enumeration value="Король" />
<xs:enumeration value="Ферзь" />
<xs:enumeration value="Ладья" />
<xs:enumeration value="Слон" />
<xs:enumeration value="Конь" />
<xs:enumeration value="Пешка" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="TypeColor">
<xs:restriction base="xs:string">
<xs:enumeration value="Белый" />
<xs:enumeration value="Черный" />
</xs:restriction>
</xs:simpleType>
</xsd:schema>
Чтобы продемонстрировать универсальные возможности языка разметки XML, я покажу, как с его помощью описывать любые математические формулы. Для этого существует специальный математический XML-словарь, который носит название MathML. В качестве иллюстрации сделаем описание основного тригонометрического тождества, знакомого всем со школьной скамьи:
sin2x + cos2x = 1
Наше представление будет иметь вид:
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mrow>
<msup>
<mi>sin</mi>
<mn>2</mn>
</msup>
<mi>x</mi>
<mo>+</mo>
<msup>
<mi>cos</mi>
<mn>2</mn>
</msup>
<mi>x</mi>
<mo>=</mo>
<mn>1</mn>
</mrow>
</math>
Как видите, корневым элементом словаря MathML служит элемент math, для которого определяется пространство имен с идентификатором http://www.w3.org/1998/Math/MathML. Для описания чисел служит элемент mn, буквенных переменных или функций — mi, операций — mo, возведения в степень — msup. Все элементы заключены в элемент-контейнер mrow (строка).
В интернете существует замечательный ресурс MathML Central www.mathmlcentral.com/Tools/FromMathML.jsp, где вы можете потренироваться в создании собственных XML-документов. По тексту, который вы введете в специальную форму, будет сгенерирована математическая формула в виде рисунка.
Как связать XML-документ со своей схемой?
Как связать теперь созданную нами схему с теми XML-файлами, которые должны будут ей соответствовать? Дадим XSD-файлу нашей схемы имя chess.xsd и положим его в каталог 'ToolBar/0809/XML/' журнального сайта www.lki.ru. Добавим к нашему корневому элементу POSITION в XML-документе следующие атрибуты:
<POSITION xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.lki.ru/ToolBar/0809/XML/сhess.xsd">
Как видите, вначале мы задействовали новое пространство имен с аббревиатурой xsi — уже не для определения схем, а для их экземпляров (XMLSchema-instance) и в рамках этого пространства имен присвоили атрибуту noNamespaceSchemaLocation URL нашей схемы.
Если бы мы захотели создать XSD-схему для второй версии нашего XML-словаря (напомню, в ней упор сделан на атрибуты элемента FIGURE), то ее отличия от данной схемы состояли бы лишь в том, что вместо элементов NAME, COLOR и PLACE составной тип FigureType описывал бы соответствующие атрибуты name, color и place:
<xsd:complexType name="TypeFigure">
<xsd:sequence>
<xsd:attribute name="name" type="TypeName" use="required" />
<xsd: attribute name="color" type="TypeColor" use="required" />
<xsd: attribute name="place" type="xsd:string" use="required" />
</xsd:sequence>
</xsd:complexType>
XSD-атрибут use установлен для атрибутов наших шахматных фигур в значение «required», чтобы гарантировать обязательность их использования. Этим, собственно, и исчерпываются различия в схемах для двух версий нашего словаря шахматных позиций.
Как проверить корректность XML-файла?
Корректность создаваемого нами XML-файла может пониматься в двух смыслах:
соответствие правилам XML-стандарта вообще. Документы, удовлетворяющие этому стандарту, называются правильными (по-английски — well-formed);
соответствие правилам данного XML-словаря, задаваемым DTD-декларацией или XSD-схемой. Документы, соблюдающие эти правила, называются валидными (от английского слова valid).
Для проверки файлов на правильность и валидность существуют специальные программы. Лучшей из них на сегодняшнем рынке является, на мой взгляд, XmlSpy от компании Altova GmBh (www.altova.com). Эта программа оснащена впечатляющим инструментарием, помогающим создавать документы, их схемы и декларации. Это и система подсказок, и возможность создать по XML-образцу декларацию или схему и наоборот. Единственным недостатком этой программы, пожалуй, является только ее относительно высокая цена.
Из бесплатных программ я могу порекомендовать XmlPad от группы WMHelp.com. Скачать ее последнюю версию можно отсюда: www.wmhelp.com/xmlpad3.htm.
Разумеется, все вышеизложенное не сможет заменить огромное количество книг, которое уже написано на эту тему, и огромное количество сайтов, ей посвященных. И конечно, я не смогу рассказать об этом языке все, что следует о нем знать, чтобы заниматься этим профессионально.
Однако я попытался лишь заинтересовать языком разметки XML тех, кто о нем почти ничего не слышал. Дать отправную точку для дальнейшего изучения тем, кто уже что-то об этом знает. Мне хотелось на простом и всем понятном игровом примере — потому и выбрана шахматная позиция — показать, что ничего сложного в этом нет, что освоить и использовать эту совсем еще молодую, но бурно развивающуюся технологию без труда сможет каждый.
Это интересно: возможно, кого-то из читателей заинтересует сама шахматная задача, которую я выбрал в качестве примера шахматной позиции исключительно за сочетание высокой информативности с небольшим количеством фигур на доске. Если захотите решить ее сами, закройте временно этот абзац листом бумаги. Если захотите узнать или сверить решение, то вот оно — простое и красивое: белый слон на с8! Если черный король побьет слона, получит мат ферзем на a8, если же попытается уйти — получит мат на b7.