Алексей Валиков - Технология XSLT
[7] NmToken ::= (NameChar)+
[8] NmTokens ::= NmToken (S NmToken)*
Символьные данные могут заключаться в кавычки для того, чтобы формировать литералы. В XML определены следующие литералы: значение сущности (EntityValue), значение атрибута (AttValue), системный литерал (SystemLiteral), а также PubidLiteral — литерал, определяющий публичный идентификатор ресурса (см. раздел "Определение сущности" данной главы):
[9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"'
| "'" ([^%&'] | PEReference | Reference)* "'"
[10] AttValue ::= '"' ([^<&"] | Reference)* '"'
| ([^<&"] | Reference)* "'"
[11] SystemLiteral ::= ('"' [^"]* '"')
| ("'" [^']* "'")
[12] PubidLiteral ::= '"' PubidChar* '"'
| "'" (PubidChar - "'")*
[13] PubidChar ::= #x20 | #xD | #xA
| [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
В литералах EntityValue и AttValue допустимо использовать продукции сущностей (PEReference, Reference). Это означает, что при определении значений сущностей и атрибутов можно использовать ссылки на сущности, например, в элементе заданном как:
<song title="Крейсер "Aвpopa" "/>
атрибут title имеет значение крейсер "Аврора". Двойные кавычки были определены посредством встроенных сущностей.
Символьные данные, которые задаются продукцией CharData, могут состоять из любых символов, кроме символов "<" и "&", которые используются в XML в качестве управляющих. CharData главным образом используется в секциях CDATA, и, соответственно, не может содержать терминирующую последовательность "]]>".
[14] CharData ::= [^<&]* - ([^<&]* ']]>' [^<&]*)
XML-документы с точки зрения спецификации
Теперь, когда мы разобрали практически все структурные единицы XML, осталось определить стандартным образом синтаксис для самих XML-документов. Им соответствует продукция document:
[1] document ::= prolog element Misc
Итак, XML-документ состоит из пролога, единственного корневого элемента и дополнительного нетерминала Misc, который может включать инструкции по обработке, комментарии и пробельные символы:
[27] Misc ::= Comment | PI | S
Остановимся отдельно на прологе XML-документа. Пролог состоит из необязательной декларации XML (XMLDecl), необязательной декларации типа документа (doctypedecl), инструкций, комментариев и пробельных символов:
[22] prolog ::= XMLDeci? Misc* (doctypedecl Misc*)?
В зависимости от того, насколько строго документы соответствуют спецификации XML и собственным DTD-объявлениям, они могут быть хорошо оформленными (well-formed) и правильными (valid).
Хорошо оформленный документ соответствует всем синтаксическим правилам XML и некоторым дополнительным ограничениям, например:
□ имя открывающего тега элемента должно совпадать с именем его закрывающего тега;
□ имена атрибутов элемента не должны повторяться;
□ в значении атрибута нельзя использовать символ "<". Этот символ должен обязательным образом заменяться на сущность;
□ сущности должны быть определены до использования;
□ сущности-параметры могут быть использованы только в блоках DTD;
□ документ должен иметь единственный корневой элемент, содержащий все остальные элементы и символьные данные этого документа. Вне корневого документа допускаются только комментарии, инструкции по обработке, декларация XML и блок DTD.
Правильные документы должны быть хорошо оформленными, и при этом их логическая структура должна удовлетворять объявлениям, которые содержатся в декларации типа документа (DTD).
Для того чтобы документ мог быть обработан различными приложениями стандартным образом, он должен как минимум быть хорошо оформленным. Выполнение этого требования означает, что документ корректен с точки зрения синтаксиса, и для его логического представления можно использовать любую из стандартных моделей. Например, если в элементе документа приведены два атрибута с одинаковыми именами, возможно, с точки зрения автора, это логично и корректно, однако, стандартными средствами такой документ обработать не удастся.
Требование правильности означает четкое соответствие выбранной логической схеме документа. Объявления декларации типа документа накладывают на логическую структуру документа определенные ограничения с тем, чтобы он мог быть стандартным образом обработан не только синтаксическими, но и семантическими процессорами, то есть программами, которые не только могут распознать синтаксис XML-документа, но и "понять" его смысл, переданный разметкой.
Использование технологии XML
Вряд ли удастся описать все множество приложений и задач, в которых можно успешно применять XML-технологии, однако существуют области, в которых использование XML стало уже классикой. Чуть ниже мы рассмотрим несколько наиболее типичных классов задач XML.
Пока же необходимо сказать следующее — несмотря на всю мощь XML, это далеко не панацея и не решение всех проблем, которые могут возникнуть. Нужно хорошо понимать, что XML — это всего лишь формат описания данных. Четкий, конкретный, независимый, мощный формат описания данных — но не более! XML-технологии могут решить проблемы представления, несоответствия синтаксиса семантике и многие другие проблемы организации данных в документе, но они не смогут решить чисто программистских задач — как обрабатывать эти документы. XML не имеет особого смысла вне прикладных задач.
В качестве типичного примера можно привести язык XSLT (язык расширяемых стилей для преобразований, extensible Stylesheet Language for Transformations), который находится в фокусе этой книги. Программы, написанные на XSLT, называются преобразованиями, и они являются в прямом смысле XML-документами, но при этом удовлетворяют логической схеме языка XSLT. При этом преобразования не имели бы смысла без XSLT-процессора, который может применять их к другим документам. Они были бы просто текстом.
Создание XML-документов без программного обеспечения, которое будет понимать их семантику — это все равно, что писать программы на языке программирования, для которого не существует трансляторов и интерпретаторов. Они могут быть безупречно корректными, но совершенно бесполезными.
Стандартизированный и совсем не сложный синтаксис XML позволил многим компаниям разработать средства для синтаксического разбора XML-документов. Программы такого рода называют XML-парсерами (англ. parse — разбирать, анализировать). В настоящее время существует два основных типа XML-парсеров: SAX-парсеры и DOM-парсеры. Оба типа широко используются в различных приложениях — парсеры избавляют от необходимости писать собственные синтаксические анализаторы, штудировать спецификации и так далее. Мы коротко опишем каждый из этих типов.
SAX-парсеры
SAX расшифровывается как Simple API for XML, что означает буквально "Простой прикладной интерфейс программирования для XML". Это так и есть — идеология SAX очень проста. Программист должен описать, как следует обрабатывать ту или иную конструкцию документа, а парсер при обработке документа уже сам будет выполнять соответствующие действия. Иными словами, обработка документа производится в виде реакции на события, которые возникают, когда парсер встречает в документе тот или иной элемент, атрибут, комментарий и так далее.
В отличие от DOM-парсеров, SAX-парсеры не создают никакого внутреннего представления документа, оставляя эту задачу на совести программиста. Вследствие этого SAX-парсеры менее требовательны к ресурсам, что часто бывает критичным. Однако это никак не сказывается на их функциональности, таким образом SAX-парсеры являются незаменимыми инструментами для синтаксического разбора XML-документов. Зачастую, более сложные DOM-парсеры используют SAX как составную часть.
DOM-парсеры
Как уже было упомянуто абзацем выше, легкие SAX-парсеры не создают внутреннего представления ХМL-документов, вполне справедливо считая, что этим придется заняться программисту.
Вместе с тем, древовидная организация данных в ХМL-документах настолько очевидна, что внутренние представления, которые использовались в совершенно разных приложениях, совпадали практически в точности. Такая ситуация привела к решению разработать единый интерфейс не для обработчика документа, как это было сделано в SAX, а для внутреннего представления XML-документа целиком.
Набор таких интерфейсов получил название DOM (document object model, объектная модель документа). DOM-парсер обрабатывает документ, создавая при этом его внутреннее объектное представление. При этом DOM содержит только определения интерфейсов, никоим образом не регулируя внутреннюю реализацию самой модели документа. Все обращения к данным и структуре, которыми обладает документ, происходят посредством вызова методов, определенных в соответствующих интерфейсах.