![]() |
|
... eXtensible Markup Language Продолжение. Начало в КГ №27 В прошлый раз мы остановились на описании спецификации DTD для XML-документов. Это очень важный момент, так как правильно составленный DTD позволяет гарантировать структурированность XML-документа и выявление всех неточностей. В этой статье мы продолжим знакомство с XML и его расширениями. Поговорим о пространствах имен в XML. Эта заслуживающая внимания тема имеет место не только в XML, но и во многих языках программирования, таких, как, например, C++. По мере того, как появляются все новые и новые XML-совместимые языки разметки, разработчики предпочитают использовать уже созданные, нежели создавать свой собственный, с нуля. Однако, имена некоторых элементов могут совпадать в двух разных языках разметки. И анализатор не сможет понять, к какому языку отнести данный элемент. Решению таких неоднозначностей и служат пространства имен (namespaces). Приведем пример XML-документа, в котором используются пространства имен. <nsp1:root xmlns:nsp1 = "http://www.litvinuke.hut.ru/test-ns1" xmlns:nsp2 = "http://www.litvinuke.hut.ru/test-ns2"> <nsp1:node> <nsp1:element> Элемент 1</nsp1:element> <nsp1:element> Элемент 2</nsp1:element> <nsp1:element> Элемент 3</nsp1:element> </nsp:node> <nsp2:node> <nsp2:element> Элемент 1</nsp2:element> <nsp2:element> Элемент 2</nsp2:element> <nsp2:element> Элемент 3</nsp2:element> </nsp2:node> </nsp1:root> Как видно из этого примера, пространства имен определяются внутри корневого элемента. xmlns:nsp1 = "http://www.litvinuke.hut.ru/test-ns1" определяет пространство имен c идентификатором nsp1. "http://www.litvinuke.hut.ru/test-ns1" наделяет каждое из пространств имен уникальностью, нет необходимости в указании валидного (существующего) URL. Главное, чтобы он был уникален. Это сродни именованию пакетов в Java. После того как вы определили необходимые пространства имен, каждый элемент, принадлежащий определенному пространству, должен помечаться как таковой. Как это делать, показано на приведенном примере. В первом случае элемент <node> </node> принадлежит пространству имен nsp1, а второй — nsp2. Это же относится и к элементам <element> </element> . Таким образом мы решили проблему неопределенности для анализатора XML-документа и подчеркнули уникальность этих элементов. Попытаемся определить DTD для нашего примера. По спецификации в DTD мы также вправе использовать необходимые префиксы пространств имен. Вот как это будет выглядеть: <!DOCTYPE nsp1:root [ <!ELEMENT nsp1:root (nsp1:node, nsp2:node)*> <!ATTLIST nsp1:root xmlns:nsp1 CDATA #FIXED "http://www.litvinuke.hut.ru/test-ns1" xmlns:nsp2 CDATA #FIXED "http://www.litvinuke.hut.ru/test-ns2"> <!ELEMENT nsp1:node (nsp1:element)*> <!ELEMENT nsp1:element (#PCDATA> <!ELEMENT nsp2:node (nsp2:element)*> <!ELEMENT nsp2:element (#PCDATA> ]> Вот так могло бы выглядеть определение DTD для нашего XML-документа. Для того чтобы определить пространство имен, используемое по умолчанию (написание элементов без префиксов), нужно задать значение атрибута xmlns в корневом элементе, например: <root xmlns = "http://www.litvinuke.hut.ru/ test-ns1" xmlns:nsp = "http://www.litvinuke.hut.ru/ test-ns2"> <node> <element> Элемент 1</element> <element> Элемент 2</element> <element> Элемент 3</element> </node> <nsp:node> <nsp:element> Элемент 1</nsp:element> <nsp:element> Элемент 2</nsp:element> <nsp:element> Элемент 3</nsp:element> </nsp:node> </root> Так мы избавились от необходимости использовать несколько префиксов. Пространство имен по умолчанию применяется ко всем элементам XML-документа без префикса. Использование пространств имен не является обязательным, и многие их игнорируют. Но если вы рассчитываете на то, что вашими разработками будут пользоваться другие, то лучше принять правила хорошего тона и включить в свои XML-документы namespaces. Поговорив о пространствах имен, плавно переходим к следующей спецификации — XLink. Из названия можно догадаться, что эта спецификация предназначена для стандартизации связывания XML-документов друг с другом. Казалось бы, зачем нужен XLink, когда уже существуют гиперссылки HTML? На самом деле HTML-гиперссылка является одним из видов ссылок, определяемых с помощью XLink. Потом, обычные гиперссылки не могут позволить осуществлять связи "один-ко-многим" и прочее. Давайте рассмотрим, как и какие виды ссылок мы можем описывать при помощи XLink. Для начала один нюанс. Для использования xlink необходимо объявить в XML-документе соответствующее пространство имен: <root xmlns:xlink = http://www.w3c.org/ 2002/xlink/namespace/ > </root> Только после этого вы можете объявлять ссылки XLink. Рассмотрим существующие типы ссылок. Их всего семь. simple — представляет собой обыкновенную ссылку, полный аналог гиперссылки в HTML. extended — для ссылок этого типа возможны разнообразные связи: один-ко-многим, двусторонняя связь и пр. locator — ссылка этого типа унифицирует элемент, ссылающийся на удаленный ресурс. arc — используется совместно с exten-ded-ссылкой и определяет различные атрибуты переходов, поведение и пр. resource — указывает на локальные ресурсы. Используется совместно с extended. title — определяет заголовки ссылок. none — не ссылка. Используется для условных конструкций. Атрибуты ссылок разделяются на четыре группы: местонахождения удаленного ресурса или локального, направления ссылок и атрибуты поведения. Атрибуты поведения определяют, каким образом ссылка будет активироваться. В случае с HTML все очень статично: переход осуществляется по нажатию на область ссылки (только с использованием различных скриптовых вставок, например на JavaScript, мы можем немного изменить это условие, но это уже будет ссылка, объявленная не средствами HTML). К первой группе относится атрибут href. Он определяет ресурс, на который указывает ссылка, в формате URI. Ко второй — атрибуты to и from. В основном предназначены для выдачи контекстно-зависимой помощи. За дополнительной информацией по этим атрибутам обращайтесь к спецификации XLink по адресу http://www.w3c.org/TR. К третьей show и actuate. show — определяет действие, которое будет выполнено при переходе по ссылке, а actuate — условие, по которому будет выполнен этот переход. Атрибут show может принимать следующие значения: embed — ресурс будет загружен в тело текущего документа (откуда была вызвана ссылка), с позиции месторасположения этой ссылки. replace — ресурс будет загружен вместо текущего документа. new — ресурс должен быть открыт в новом окне. undefined — не определено. Власть переходит в руки анализатора либо программы, обрабатывающей этот документ. Значения атрибута actuate: onLoad — переход по загрузке текущего документа. onRequest — переход по внешнему прерыванию (например, нажатие клавиши мыши). undefined — аналогично, как и у show. Приведем несколько примеров ссылок в соответствии со спецификацией XLink: <my_link xlink:type = "simple" xlink: show = "replace" xlink:actuate = "onRequest" xlink:href = "http://www.litvinu-ke.hut.ru/articles/aboutxml2.rtf"> eXtensible Markup Language (2)</my_link> <new_link xlink:type = "simple" xlink: show = "new" xlink:actuate = "onLoad" xlink:href = "http://www.w3c.org/"> WWW Consortium</new_link> Указывая атрибуты ссылок Xlink, необходимо использовать префикс определенного вами пространства имен. В нашем случае это xlink. По активации первой ссылки путем внешнего прерывания текущий документ будет заменен на удаленный ресурс, определенный атрибутом xlink:href. Во втором случае ссылка активируется сразу по загрузке текущего документа, и ресурс будет загружен в новом окне. Было бы нечестно не рассмотреть пример использования расширенных ссылок. Они используются в основном для того, чтобы указывать на несколько ресурсов одновременно. <ext_link xlink:type = "extended"> <element xlink:type = "locator" xlink: href = "http://www.litvinuke.hut.ru/in-dex.php" xlink:role = "main"/> <element xlink:type = "locator" xlink: href = "http://www.litvinuke.hut.ru/ lnk101.html" xlink:role = "about"/> </ext_link> Новый атрибут xlink:role предназначен для описания ссылки. Он относится к группе семантических атрибутов ссылок. В эту группу также входит атрибут title. Столь же плавно перейдем к рассмотрению очередной и, наверное, последней спецификации на этот раз — это XPointer. Предназначена она для стандартизации описания путей месторасположения в самом XML-документе. Эта спецификация намного сложнее и объемнее, нежели Xlink, и здесь очень бы пригодились знания в организации DOM (Document Object Model) дерева. Но об этом мы поговорим намного позже. Сейчас на горизонте XPointer. Эта спецификация фактически целиком основана на спецификации XPath. XPointer, равно как и XSLT, использует язык XPath для описания URL на элементы DOM-дерева (части XML-документа). Путь к какой-либо определенной части XML-документа разбивается на несколько этапов (шагов), разделяемых символами / (прямой слэш). Например: /node::element За двойным двоеточием следует шаблон, по которому мы адресуем наш указатель. В контексте данного примера мы ссылаемся на все элементы element, находящиеся в элементе node. Начальный / означает абсолютное местонахождение корневого элемента. Вместо или совместно с именами обычных элементов можно использовать специальные ключевые слова: child — определяет вложенные узлы; descendant — определяет любые узлы, которые находятся ниже уровня текущего узла; parent — определяет родительский узел для текущего элемента; ansector — любые узлы, которые содержат текущий узел; preceding — любые из узлов, расположенных выше текущего; following — любые из узлов, распложенных ниже текущего; preceding-sibling — предыдущий узел, у которого общий родитель с текущим узлом (брат); following-sibling — следующий узел-брат; attribute — определяет атрибут текущего узла; namespace — определяет пространство имен текущего узла; self — определяет сам текущий узел; descendant-or-self — текущий узел либо все остальные узлы-потомки; ancestor-or-self — текущий узел либо все остальные узлы-родители. Существуют также некоторые параметры для более гибких фильтров на выборки узлов. Помимо этих параметров, для того чтобы ограничить круг возвращенных узлов, существуют предикаты. Приведем пример: <root> <node> <element type = "type1"> Элемент 1</element> <element type = "type2"> Элемент 2</element> </node> </root> Для того чтобы выбрать элемент <element/>, у которого значение атрибута type == "type1", мы можем использовать следующую конструкцию: /node::element[attribute::type = "type1"] Как видно, предикаты заключаются в квадратные скобки. Для придания функциональности предикатам в них можно использовать набор предопределенных функций. Я не буду приводить их полный список по той причине, что он довольно объемный, но вот самые широко используемые из них: number position() — возвращает число, соответствующее месторасположению текущего узла; node-set id(object) — выбирает узлы по его уникальному идентификатору (атрибут ID); number count(node-set) — возвращает количество узлов в node-set; boolean start-with(string, string) — возвращает истину, в случае если в начале первой строки содержится вторая строка. Или ложь, если это не так; boolean contains(string, string) — возвращает истину, если в первой строке есть вхождение второй строки, иначе ложь; boolean not(boolean) — возвращает результат выполнения операции NOT над выражением; number round(number) — округляет число до наиболее близкого целого значения. Я привел список некоторых из существующих функций лишь для того, чтобы вы могли видеть, что они могут вам дать. Для более детального ознакомления с полным списком обратитесь к спецификации по XPointer и XPath. Также желательно знать, что после оператора :: не обязательно должно идти имя выбираемых узлов. Например, если мы хотим выбрать текст из определенного элемента, то можно воспользоваться типом проверки text(), если комментарии, то — comment() и пр. Например: /node::text()[attribute::type = "type1"] В этом случае в результате мы имеем "Элемент 1". Указатель XPointer выглядит, как обычная функция, которой передается в качестве параметра выражение XPath: xpointer(/node::element[attribute::type = "type1"]) Приведем пример использования функций в предикатах: <root> <node id = "1"> <element type = "type1"> Элемент 1 </element> <element type = "type2"> Элемент 2 </element> </node> <node id = "2"> <element type = "type2"> Элемент 3 </element> <element type = "type2"> Элемент 4 </element> </node> </root> xpointer(id("1")/child::element[position() = 2]) Будет выбран "<element type = "type2"> Элемент 2 </element> " xpointer(id("1")/child::text()[attribute::type = "type2"]) Будут выбраны следующие строки: "Элемент 2, "Элемент 3", "Элемент 4". На этом все. В следующий раз мы затронем не менее важные темы, касающиеся XML и его спецификаций. Алексей Литвинюк © Компьютерная газета
|
|