Адресация на языке XPath
Для удобной работы с документом XML необходимы средства, позволяющие точно адресовать ту или иную его часть: отдельную точку, множество точек, какой-либо участок или множество участков документа. Такие средства предоставляет язык XPath, разработанный консорциумом W3C. Язык XPath, как и XPointer, - не реализация XML. Его основу составляют выражения различных типов, в числе которых логический, числовой и строковый тип. В выражениях записываются константы, переменные и функции, входящие в состав XPath. Они связываются операциями, характерными для данного типа. В результате вычисления выражения получается указание на какой-то один или сразу несколько участков документа.
Очень часто выражение строится подобно пути к файлу в файловой системе, откуда и происходит название языка "XML Path", сокращенно XPath. При этом документ XML рассматривается как дерево.
Атрибут
У каждого атрибута документа должен быть один информационный пункт. Если процессор распознает пространства имен, то используемые для их определения атрибуты в списке данных информационных пунктов представлены не будут.
У информационных пунктов атрибутов имеются следующие свойства:
Фрагмент URI имени атрибута, при наличии. Локальная часть имени атрибута. Упорядоченный список информационных пунктов символов для каждого символа в (нормализованном) значении атрибута. При желании в этот список можно также включить информационные пункты маркеров начала и конца сущностей для всех ссылок на объекты в значении атрибута.По желанию разработчика можно указать флаг, определяющий, значение этого атрибута определено либо задано по умолчанию в определении DTD или в схеме.По желанию разработчика можно указать значение атрибута по умолчанию из DTD.По желанию разработчика можно указать тип, объявленный для атрибута в определении DTD.
Декларация пространства имен
Для каждого пространства имен существует одна декларация пространства имен, она объявляется (или подразумевается) как атрибут элемента.
Информационный пункт декларации пространства имен имеет следующие свойства:
Объявляемое пространство имен. Это фрагмент имени атрибута, следующий за префиксом xmlns:.Абсолютный идентификатор URI объявляемого пространства имен. Необходимо сообщить либо это свойство, либо следующее далее свойство потомка (описывающее текст), либо то и другое.Упорядоченный список символьных ссылок на информационные пункты символов, которые составляют содержание значения атрибута. В него могут входить также маркеры начала и конца сущности, показывающие расположение ссылок на сущности. Должно присутствовать либо это, либо предыдущее свойство. Консорциум W3C добавил это свойство, чтобы обеспечить возможность определять пространства имен в будущих версиях не по URI.
Декларация типа документа
Один информационный пункт декларации типа документа можно указать при желании разработчика и при наличии такой декларации.
У информационного пункта декларации типа документа могут быть следующие свойства:
Ссылка на информационный пункт сущности для внешнего подмножества DTD.Упорядоченный список ссылок на информационные пункты комментариев и команд обработки, присутствующие в DTD.
Дерево документа
Язык XPath рассматривает документ XML как дерево. Корнем дерева будет корневой элемент документа, а узлами - вложенные элементы, содержимое элемента (текстовый узел) или его атрибуты. Кроме того, в узлах дерева могут находиться комментарии, инструкции по обработке, пространства имен.
Схема element() не учитывает текстовые узлы и узлы-атрибуты. Она отмечает только вложенные элементы. Но схема xpointer() должна строго следовать правилам языка XPath и учитывать текстовые узлы, даже если они содержат только пробельные символы. Впрочем, многие программы-анализаторы языка XPointer не следуют этому правилу. Например, функция last() разными программами-анализаторами будет вычислена по-разному в зависимости от того, как они построят дерево документа.
Язык XPath представляет документ в виде дерева, корнем которого служит корневой элемент документа. От корня отходят ветви, заканчивающиеся узлами. Узлами служат, например, вложенные элементы, их атрибуты и тексты, составляющие содержимое корневого элемента. От каждого вложенного элемента отходят свои ветви, рекурсивно повторяющие ветви корневого элемента. Таким образом, у каждого узла может быть только один узел - "предок", причем предком может быть только узел корневого или другого элемента дерева, но не атрибут и не текстовый узел.
Документ
Информационный пункт документа должен быть всегда ровно один, он содержит информацию о документе в целом и имеет следующие свойства:
Список порожденных информационных пунктов в порядке их следования в оригинальном документе. Сюда входит, по крайней мере, один информационный пункт элемента. Кроме того, список должен содержать все информационные пункты команд обработки, определенные вне контекста корневого элемента документа. По желанию разработчика в этот список могут входить также информационные пункты комментариев, находящихся вне корневого элемента документа, а также информационный пункты декларации типа документа (если в оригинальном документе такая информация определена).Неупорядоченный набор из информационных пунктов нотаций для всех нотаций документа.Неупорядоченный набор из информационных пунктов сущностей для всех не анализируемых сущностей документа. По желанию разработчика в этот список могут входить также информационные пункты для анализируемых сущностей, для сущности документа и для внешнего множества DTD.При желании разработчик может включить сюда также идентификатор URI обрабатываемого документа.
Дополнения языка XPointer
Исторически сложилось так, что язык XPath был создан на два года раньше языка XPoinler. Поэтому создатели языка XPointer внесли в него дополнения, расширившие конструкции языка XPath.
Во-первых, кроме узлов дерева, язык XPointer рассматривает точки (points) и области (ranges).
Точкой язык XPointer называет позицию между символами документа XML.
Область занимает пространство между двумя точками: начальной точкой и конечной точкой. Начальная и конечная точки могут располагаться в любом месте документа XML, следовательно, область может пересекать элементы документа XML, не совпадая с узлами дерева. Разумеется, начальная точка должна встретиться в документе раньше конечной точки.
Точки, области и узлы вместе образуют местоположение. В результате всякого поиска отыскивается некоторое местоположение или набор местоположений.
Во-вторых, в схему xpointer() введены новые функции range(), stringrange(), range-to(), range-inside (), here(), origin (), start-point(), end-point(), работающие с точками и областями.
Эти дополнения позволяют гораздо точнее адресовать различные части документа, вплоть до отдельного символа.
Все действия с точками и областями выполняются с помощью перечисленных функций.
Информационные пункты
Имеющиеся пятнадцать различных пунктов информации совместно составляют правильно оформленный документ XML. Некоторые из этих пунктов должны присутствовать в грамматически разобранном (проанализированном) представлении документа XML, чтобы он мог быть конгруэнтным (по стандартам W3C) оригинальному документу, другие можно при желании опустить. Назовем типы информации (информационных пунктов):
Один информационный пункт документа (обязателен)Один или больше информационных пунктов элементов (обязательно) Информационные пункты атрибутов (обязательны) Информационные пункты команд обработки (обязательны) Информационные пункты символов (обязательны) Ссылка на пропущенные информационные пункты сущностей (обязательны) Информационные пункты комментариев (необязательны) Информационный пункт декларации пункта документа (необязательны) Информационные пункты объектов (обязательны для не анализируемых сущностей, необязательны для анализируемых сущностей) Информационные пункты нотации (обязательны) Информационные пункты маркера начала сущности (необязательны) Информационные пункты маркера конца сущности (необязательны) Информационные пункты маркера начала раздела CDATA (необязательны) Информационные пункты маркера конца раздела CDATA (необязательны) Информационные пункты декларации пространства имен (обязательны)
Необязательные пункты являются необязательными в том смысле, что они требуются в грамматически разобранном представлении документа для того, чтобы оно было достаточно конгруэнтно оригиналу в соответствии с определением InfoSet консорциума W3C.
Использование простых указателей в ссылках
Ссылки на информационный ресурс, содержащий указатели, записываются по правилам языка XLink, в который добавлена конструкция, взятая из языка HTML, а именно в ссылке на ресурс перед указателем ставится знак решетки #:
<myLink xlink:type="simple" xlink:href="mydoc.xml#label02" />
Ссылка, записанная в том же самом документе mydoc.xml, начинается с решетки и выглядит так:
<myLink xlink:type="simple" xlink:href="#label02" />
Если в документе записано несколько одинаковых указателей label02, то ссылка будет связана с первым из них.
Как видите, простые указатели языка XPointer только дублируют конструкции, давно применяемые в HTML и XML. Все новые возможности языка реализованы через указатели, основанные на схеме.
Использование указателей в ссылках
Указатели, основанные на схеме, используются точно так же, как и простые указатели. Они записываются в атрибутах элементов-ссылок после пути к файлу и отделяются от него "решеткой":
<myLink xlink:type="simple" xlink:href="mydoc.xml#element(color/3) "/>
Язык запросов XQuery
После того как язык XML научился делать ссылки на языке XLink, создавать указатели XPointer на каждую точку документа и тонко адресовать любые части документа с помощью XPath, остался последний шаг: научиться извлекать найденную по адресу информацию из любых участков документа и оформлять ее в виде элементов документа XML. Язык XQuery как раз и призван сделать этот последний шаг.
Поскольку перед извлечением информации из документа надо ее отыскать язык XQuery разрабатывался в тесной связи с языком XPath 2.0. Более того, большинство конструкций языка XPath 2.0 созданы в расчете на написание запросов. Многие выражения XPath, такие как выражение //ААА/ВВВ, делают запрос на поиск информации в документе XML. Поэтому язык XQuery можно считать расширением язык XPath 2.0. В нем можно применять почти все, что есть в языке XPath 2.0.
Единственное ограничение - в первой версии языка XQuery, выражения, определяющие путь, можно направлять только по 6 осям из 13, имеющихся в языке XPath: child (по умолчанию), descendant, attribute, self, descendant-or-self и parent.
Основной единицей языка XQuery, как и языка XPath, служит выражение, причем набор выражений, перечисленных через запятую, тоже считается выражением. Это так называемая "операция запятая", объединяющая несколько выражений в одно, вычисляемое последовательно слева направо. Результат вычисления выражения, как и в языке XPath, - последовательность узлов и/или атомарных значений. Виды узлов и типы атомарных значений таковы же, как и в XPath 2.0.
Запрос в языке XQuery тоже оформляется как выражение. Разница заключается в том, что и результате вычисления выражения получается последовательность, а в результате выполнения запроса должен получиться один или несколько документов XML. Значит, в первую очередь язык XQuery должен научиться конструировать элементы XML. За это отвечают конструкторы.
Элемент
Для каждого элемента документа XML должен существовать один информационный пункт.
Информационные пункты элемента имеют следующие свойства:
Упорядоченный список информационных пунктов порожденных элементов, команд обработки, ссылок на пропущенные сущности и символов в порядке их следования в документе. Этот список может быть пустым. При желании разработчика в него можно включить также информационные пункты комментариев. Кроме того, в список могут входить также информационные пункты маркеров: начала сущности, конца сущности, начала данных типа CDATA и конца данных типа CDATA; эти пункты могут входить только соответствующими парами (не должно быть маркера начала без маркера конца и наоборот).Не упорядоченный список информационных пунктов атрибутов, по одному для каждого атрибута элемента. В набор входят также и атрибуты по умолчанию. Обратите внимание: если у элемента имеется атрибут пространства имен, а анализатор не распознает пространства имен, атрибут, включен в этот список для спецификации пространства имен; в противном случае он не будет туда включен. Этот список может быть пустым.Содержащийся в имени элемента фрагмент, соответствующий универсальному идентификатору ресурса (URI), предоставляемый процессором пространства имен. Если анализатор не осуществляет обработки пространств имен или если пространство имен для элемента не определено, URI будет равен нулю.Локальная часть имени элемента. Если анализатор не обрабатывает пространства имен, эта часть содержит все имя целиком (включая название пространства имен и двоеточие при наличии идентификатора пространства имен в имени элемента). В противном случае она представляет собой только локальную часть имени (после двоеточия) или имя целиком (если пространство имен не указано).Неупорядоченный набор ссылок на информационные пункты деклараций пространства имен. Они соответствуют пространствам имен, объявленным в составе этого элемента.По желанию разработчика сюда может входить также неупорядоченный список информационных пунктов деклараций пространств имен, которые соответствуют пространствам имен, объявленным в области действия этого элемента (т.е. в самом элементе или в одном из его предков).
Команды обработки
Для каждой команды обработки документа должен существовать информационный пункт команды обработки. Декларация ХМL и декларации внешних анализируемых объектов сами по себе командами обработки не считаются.
Информационные пункты команд обработки содержат следующие свойства:
Цель команды обработки. Это первый знак, следующий за символами "<?" в теге команды обработки.Содержание команды обработки. Это остальной текст в теге перед закрывающими символами "?>", из которого удалено предшествующее ему пустое пространство. Может представлять собой, пустую строку.Разработчик может указать также идентификатор URI объекта, первоначально содержавшего команду обработки (если команда обработки объявлена в тексте, это будет URI обрабатываемого документа, если он известен).
в документе можно определить один
Для каждого комментария в документе можно определить один информационный пункт комментария.
Информационный пункт комментария содержит свойство - содержание этого комментария.
Конструкторы
Конструктор узлов - это выражение, которое создает и добавляет к дереву документа новые узлы.
Конструкторы могут создавать узлы каждого вида за исключением узлов пространств имен. При этом узел-элемент можно создать средствами прямого или вычисляемого конструктора, узел-атрибут, корневой узел документа и текстовый узел - только вычисляемого конструктора, а узлы-комментарии и узлы инструкций по обработке просто записываются в конструкторе прямо в том виде, в каком они затем появятся в документе.
Маркер конца объекта
Для того чтобы отметить конец текста, вставляемого из внешней анализируемой сущности, существует маркер конца сущности. Маркер не используется для параметрических сущностей.
Информационный пункт маркера конца сущности содержит свойство, представляющее собой ссылку на информационный пункт сущности для вставляемого текста.
Маркер конца раздела CDATA
Для того чтобы показать конец текста, включенного в раздел CDATA, используется один маркер конца сущности. Информационный пункт маркера конца раздела CDATA не имеет свойств.
Маркер начала раздела CDATA
Для того чтобы показать начало текста, включенного в раздел DATA, используется один маркер начала объекта. Информационный пункт маркера начала раздела CDATA не имеет свойств.
Маркер начала сущности
Для того чтобы отметить начало текста, вставляемого из внешней анализируемой сущности, имеется маркер начала сущности. Маркер не используется для параметрических сущностей.
Информационный пункт маркера начала сущности содержит свойство, представляющее собой ссылку на информационный пункт сущности для вставляемого текста.
Нотация
Для каждой объявленной в определении DTD нотации должен быть один информационный пункт нотации.
Информационные пункты нотации содержат следующие свойства:
Имя нотацииСистемный идентификатор нотации, или null, если он не был определенОбщий идентификатор нотации, или null, если он не был определенБазовый идентификатор URI, соответствующий нотации
Понятие схемы в языке XPointer
Слово "схема" в языке XPointer получило новое значение. Это запись вида
element (color/3)
похожая на запись функции и состоящая из имени схемы и данных, записанных в скобках.
Схемы, записанные в указателе, просматриваются последовательно до тех пор, пока не будет найдена точка в документе, отвечающая какой-либо схеме. После этого просмотр указателя прекращается, оставшиеся схемы не рассматриваются. В приведенном выше примере, если будет найден элемент section, то схема element (color/3) рассматриваться уже не будет.
Имя схемы - это уточненное имя типа Qname, состоящее из необязательного префикса, связанного с идентификатором пространства имен, и локальной части, отделенной от префикса двоеточием.
Имена без префиксов зарезервированы за схемами, которые определяются в рекомендациях консорциума W3C. Каждая схема, предложенная консорциумом, описывается отдельной рекомендацией. Разработчики могут вводить свои семы, снабжая их имена префиксами.
Смысл и правила записи данных зависят от вида схемы. Есть только одно общее правило, вытекающее из того, что данные записываются в скобках - все скобки, относящиеся к данным, должны быть парными или предваряться символом "каре" ("крышечкой"): xxx^(yyy или yyy^)xxx. Если же в данных встречается символ каре, то его следует удваивать: xxx^^yyy.
Разумеется, схема- это не функция, она ничего не вычисляет и не выдает никакого результата. Это просто форма записи, несколько неожиданная и непривычная для языков, основанных на XML.
Прямой конструктор элемента
Самый простой способ сконструировать элемент XML- это записать его в явном виде с открывающим тегом, атрибутами, содержимым и закрывающим тегом. Эта форма называется прямым конструктором элемента.
В прямом конструкторе, в содержимом конструируемого элемента, можно записать выражение в фигурных скобках. Оно будет вычислено, а результат вычисления подставлен в конструируемый элемент. Например:
<аgе>{10 + 20 }</аgе>
Заметьте, что если не написать фигурные скобки, то выражение не будет вычисляться, а попадет в конструируемый элемент как простой текст.
Если фигурные скобки надо понимать как простые символы, а не как команду вычисления выражения, то их следует удваивать.
В общем случае прямой конструктор элемента состоит из элемента XML. В элемент могут быть вложены другие элементы, выражения в фигурных скобках и наборы символов - содержимое элемента. Конструктор преобразует наборы символов в текстовые узлы, вычисляет выражения, рекурсивно обрабатывает вложенные элементы и формирует новый узел-элемент с вложенными узлами-элементами, узлами-атрибутами и текстовыми узлами.
Каждое выражение после вычисления даст последовательность узлов и/или атомарных значений. Для узлов из этой последовательности конструктор создаст точную копию со всеми их узлами-потомками, узлами-атрибутами, углами пространств имен, если они есть. Для каждой подпоследовательности идущих подряд атомарных значений конструктор создаст один текстовый узел, содержащий строковые представления атомарных значений с пробелом между ними.
В полученной после этого новой последовательности нет атомарных значений, а есть только узлы.
Затем все содержимое конструируемого элемента представляется одной последовательностью узлов, составленной из текстовых узлов конструктора, последовательностей, полученных после вычисления и преобразования выражений, и вложенных узлов-элементов, полученных после рекурсивной обработки вложенных в конструктор элементов. В этой последовательности не должно быть корневых узлов документа, а все узлы-атрибуты должны находиться в начале последовательности. Если эти условия не выполнены, то конструктор выдаст сообщение об ошибке и прекратит работу. Если же они выполнены, то конструктор сделает еще один шаг: он сольет все идущие подряд текстовые узлы, не оставляя между ними пробелов, в один текстовый узел.
После этого прямой конструктор создает узел-элемент с узлами-потомками из последовательности, полученной на предыдущем шаге.
В атрибутах конструктора тоже можно записать выражения в фигурных скобках, например:
<person id="92-3456" sex="{ /notion/sex[1]}">
Выражение вычисляется, каждый элемент полученной последовательности представляется строкой, а строки разделяются пробелами. Кроме выражений, значение атрибута может содержать наборы символов, которые сцепляются со строками, полученными из выражений, без всяких пробелов:
<person id="9{l + 1}-3456" sex="male">
Простые указатели
Простой указатель представляет собой имя типа NCName языка XSD, состоящее из букв, цифр, точек, дефисов и знаков подчеркивания. Имя должно начинаться с буквы. Как обычно в XML, указатель вписывается в любом атрибуте-идентификаторе типа ID, который может содержаться в любом элементе документа XML. Например:
<someElem myid="label02"> Содержимое элемента </someElem>
Атрибут-указатель в примере myid обязательно должен быть объявлен при описании схемы документа. Объявить его следует с типом ID.
направляемый фильтром
Шаг, направляемый фильтром, использует вместо оси и теста узла первичное выражение:
Первичное выражение[Предикат]
Первичное выражение выдает в качестве результата последовательность узлов и/или атомарных значений, которая затем фильтруется предикатом.
Первичное выражение - это:
число типа xs:integer, xs:decimal, xs:double;строка символов типа xs:string;значение переменной, начинающееся со знака доллара $;.вызов функции;наконец, произвольное выражение, заключенное в скобки.
Поэтому на шаге, направляемом фильтром, можно применять любое выражение, надо только заключить его в скобки.
направляемый осью поиска
Шаг, направляемый осью поиска, состоит из трех частей: оси поиска, теста узла и необязательного предиката. Ось отделяется от теста узла двумя двоеточиями, а предикат записывается после теста узла в квадратных скобках:
ось: текст узла [предикат].
Например, шаг поиска может выглядеть так:
child::section[l]
В этом примере ось поиска child показывает, что поиск охватывает все узлы, непосредственно вложенные в просматриваемый узел, за исключением узлов-атрибутов и узлов пространств имен, текст узла section выбирает из этих узлов узлы-элементы section, а предикат 1 выбирает первый из встреченных узлов-элементов section.
Каждая из трех частей шага поиска сужает первоначальную область поиска.
Ось поиска задает направление поиска, отсчитываемое от текущего узла, и его объем. Например, поиск может идти в сторону вложенных элементов или, наоборот, просматривать родительские узлы. Можно просматривать только атрибуты элементов или только соседние элементы.
Текст узла выбирает в области поиска, заданной осью, определенные узлы по их имени или типу.
Предикат содержит условия, по которым проверяет узлы, уже отобранные осью поиска и тестом узла, и делает окончательный выбор.
Схема element()
Схема element() реализует потребность ссылаться на элемент документа XML примерно в таком стиле: "сослаться на второй абзац третьего параграфа договора №5". Реализация очень проста и выглядит следующим образом:
element(/1/3/2)
В этом примере начальная наклонная черта и единица показывают, что отсчет начинается с корневого элемент. В нем выбирается третий по счету непосредственно вложенный элемент. В этом элементе выбирается второй по счету вложенный в него элемент.
Запись вида /1/3/2 называется последовательностью вложений. Она напоминает запись пути к файлу. Наклонная черта отмечает вложенный элемент подобно вложенному каталогу файловой системы, но вместо имени вложенного каталога или файла стоит натуральное число. Число, записанное за наклонной чертой, показывает порядковый номер непосредственно вложенного элемента. Отсчет элементов начинается с 1.
Поскольку в хорошо оформленном документе XML может быть только один корневой элемент, последовательность вложений обычно начинается с наклонной черты и единицы: /l. За следующей наклонной чертой перечисляются элементы, непосредственно вложенные в корневой элемент и т. д.
Перед последовательностью вложений может стоять простой указатель. В этом случае вложения отсчитываются не от корневого элемента, а от элемента, помеченного этим указателем. Применяя простой указатель, предыдущий пример можно записать так:
element (sect3a/2)
Наконец, данные в схеме element () могут состоять только из простого указателя:
element (sect3a)
Это эквивалентно написанию простого указателя без всякой схемы.
Схема xpointer()
Схема xpointer() использует для создания указателей и ссылок на них мощные средства адресации элементов и других частей документа, предоставляемые языком XPath. В схеме xpointer() данными, записываемыми в скобках, могут служить любые выражения, допускаемые в языке XPath, а также их расширения, введенные в язык XPointer.
Символ
Для каждого символа документа, не являющегося символом разметки, должен быть информационный пункт символа (обратите внимание - один информационный пункт для каждого отдельного символа). На практике расположенные рядом символы объединяют в строки или конструкции текста, а не перечисляют по отдельности (в соответствии со спецификацией W3C Infoset, это допустимо).
Информационные пункты символов содержат свойства:
Код символа в соответствии со стандартом ISO 10646 (Unicode).Флаг, показывающий, является ли символ пустым пространством внутри содержания или нет. Проверяющие на допустимость анализаторы должны всегда устанавливать этот флаг; не проверяющие на допустимость при желании могут установить этот флаг равным false.При желании разработчик может указать, был ли этот символ включен как часть предопределенной сущности XML.
Создание банка ссылок
При создании какого-либо документа на языке HTML, назовем его для определенности doc.html, в него вставляются гиперссылки на предыдущие, ранее созданные, документы и изображения. Пусть эти ресурсы лежат в файлах oldl.html, old2.html, imgl.gif. Через некоторое время появляются новые документы, назовем их newl.html, new2.html, на которые необходимо сослаться из документа doc.html. Для этого придется отыскать файл doc.html и внести в него новые ссылки. Это очень неудобно. Не говоря уже о том, что файл doc.html может быть недоступен, его уже могли скопировать на множество сайтов. Придется вносить изменения во все копии, что совершенно невозможно.
Язык XLink, в котором можно сделать ссылки и в прямом, и в обратном направлении, позволяет создать обратные ссылки из новых документов на старый документ. Но это не лучший выход из положения, потому что старый документ при каждом открытии должен отыскать и просмотреть новые документы в поисках этих ссылок. Это требует времени и знания тех адресов, где лежат эти новые документы.
К счастью, язык XLink предлагает другой, более удобный выход из этой ситуации. Мы выносим все ссылки в отдельный файл - "банк ссылок" - и в случае необходимости изменяем ссылки только в этом файле. Все документы, которым нужны ссылки, обращаются за ними в банк ссылок.
Создание ссылок на языке XLink
Язык XLink позволяет создать ссылку в одном, а использовать в других документах. Ссылка может указывать сразу на несколько документов. Сослаться можно не только на документ XML, но и на любой информационный ресурс: изображение, чертеж, программу. Можно организовать ссылку, связывающую другие документы, например, ссылка, записанную в документе docl.xml, может установить связь между документом doc2.xml и документом doc3.xml. Кроме того, язык XLink отмечает направление ссылки и позволяет организовать обратные ссылки. Эти возможности делают язык XLink чрезвычайно мощным, способным удовлетворить нужды самого привередливого разработчика.
Пространство имен языка XLink
Интересная особенность языка XLink заключается в том, что он не вводит новые элементы, а определяет только атрибуты, которые можно использовать в любых определяемых вами элементах. Каждый элемент в документе XML, использующий атрибуты языка XLink, становится ссылкой. Атрибуты введенные языком XLink, находятся в пространстве имен http://www.w3.org/1999/xlink. Как обычно, перед использованием атрибутов надо связать это пространство имен с каким-либо префиксом. Очень часто этот префикс называется xlink
<someElement xmlns:xlink="http://www.w3.org/1999/xlink> someText" </someElement>
Всего в языке XLink объявлено десять атрибутов:
атрибут type задает тип ссылки;атрибут href описывает адрес ресурса, с которым связана ссылка;атрибут show определяет способ показа полученного по ссылке ресурса;атрибут actuate устанавливает момент активизации ссылки;атрибуты label, from, to отмечают и указывают начальные и конечные пункты ссылки;атрибуты role, arcrole, title объясняют смысл ссылки.
Разумеется, кроме атрибутов языка XLink в объявляемых элементах-ссылках можно объявлять и любые другие атрибуты.
Ссылка на пропущенную сущность
Информационный пункт ссылки на пропущенную сущность должен быть определен для каждой ссылки на сущность, которая либо не была интерпретирована анализатором, не осуществляющим проверку на допустимость, либо в связи с тем, что декларация неизвестной сущности не была прочитана (например, вследствие недоступности), либо потому, что анализатор не включает внешние анализируемые сущности.
У информационных пунктов ссылок на неизвестные сущности имеются следующие свойства:
Имя сущности, на которую ссылаются.По желанию разработчика можно включить также информационный пункт ссылки на сущность для неразвернутой внешней анализируемой сущности, если анализатор прочитал декларацию.
Сущность
Не анализируемые внешние сущности должны быть представлены в виде информационных пунктов сущностей. Для каждой другой сущности в документе также может существовать информационный пункт объекта. Если сущность была объявлена несколько раз, для создания информационного пункта сущности используется только первая ее декларация.
Информационные пункты сущностей содержат такие свойства:
Тип сущности (внутренняя параметрическая сущность, внешняя параметрическая сущность, внутренняя общая сущность, внешняя общая сущность, не анализируемая сущность, сущность документа или внешнее подмножество DTD).Имя сущности. Равно неопределенному значению (null), если информационный пункт сущности представляет собой сущность документа или вешнее определение DTD. Системный идентификатор сущности. Для внутренних сущностей это свойство равно null; для сущности документа оно может быть равно null, а может содержать системный идентификатор документа.Общий идентификатор сущности, если он есть. Для внутренних сущностей равен null.Если сущность является не анализируемой, то ссылка - на информационный пункт нотации. Для других типов сущностей равен null.Базовый идентификатор URI сущности. Если сущность является внутренней, то значение этого идентификатора должно быть равно nullПо желанию разработчика можно включить текст сущности, если это внутренняя сущность.По желанию разработчика можно включить также название кодировки символов, в которой выражена сущность.Можно включить также указание на статус автономности сущности. Допустимы значения "yes", "no" и "not present".
Связи и запросы
Для того чтобы язык XML мог полностью задействовать свой потенциал, необходимо иметь способ реализации ссылок между документами XML, указатели на них и запросы к ним.
В связи с тем, что в документах XML сохраняется все 6ольше информации, возникает необходимость в разработке способа получения структурированного доступа к этой информации. Также необходимы способ определения связей между частями документов и обращения к фрагментам (или ресурсам) внутри документов, которые связаны с другими ресурсами. Эти ресурсы могут быть фрагментами как того же, так и других документов, или вовсе не относиться к формату XML.
Указатели, основанные на схеме
Указатели, основанные на схеме, состоят, как и следует из их названия, из одной или нескольких схем, записанных через пробелы. Вот пример:
xpointer(/book/chapter/section) element (color/3)
В этом примере указатель состоит из двух схем. Первая схема задает ссылку на элемент section, вложенный в элемент chapter, который, в свою очередь, вложен в коневой элемент book.
Вторая схема ссылается на третий по счету элемент из всех непосредственно вложенных в помеченный простым указателем color элемент.
Уточненные ссылки XPointer
Язык XLink позволяет организовать только внешние ссылки на информационный ресурс. Они не могут сослаться на определенное место удаленного документа или на какое-то произвольное место того документа, в котором они записаны. Такие ссылки могут быть полезны, поскольку очень часто в документах нужно организовать ссылку на определенное место того же самого документа, скажем, при создании оглавления, предметного указателя, глоссария.
В языке HTML <а>. В нем атрибутом href указывается метка того места документа, на которое мы хотим перейти. Перед меткой ставится символ "решетка" #.
Например: <a href="#ref0012"> Пункт оглавления </a>
В том месте документа, на которое мы хотим перейти, записывается тег <а> с атрибутом name и той же меткой:
<a name="ref0012"></a>
Подобную метку можно записать в удаленном документе, допустим, в файле remfile.html, и ссылаться на нее следующим образом:
<a href="http://some.com/pub/remfile.html#ref0012"> Пункт оглавления </а>
Браузер загрузит документ remfile.html и покажет ту его часть, в которой записан элемент.
<a name="ref0012"></a>
Аналогичная конструкция, разумеется, есть и в XML. По правилам XML метки создаются с помощью атрибутов типа ID, которые можно объявить в любом элементе.
Ссылки на помеченные элементы указываются атрибутами типа IDREF или IDREFS, которые тоже можно объявить в любом элементе. Проверяющий анализатор, просматривая документ XML, следит за соответствием меток и ссылок на них, отмечая как ошибку ссылку на несуществующую метку. Знак решетки # в ссылках записывать не нужно, сам тип IDREF показывает, что значение атрибута - ссылка.
Предыдущий пример, переписанный по правилам XML, будет выглядеть следующим образом. Ссылку на помеченный элемент можно записать в виде:
<item ref="ref0012"> ????? ?????????? </item> ? ???????? ??????? ????? ???: <ch id="ref0012" /> ?????????? ????????? item ? ch ?? ????? XSD ????? ????? ???: <xsd:element name="item"> <xsd:complexType> <xsd:simpleContent> <xsd:extension base="xsd:string"> <xsd:attribute name="ref" type="xsd:IDREF"/> </xsd:extension> </xsd:simpleContent> </xsd:complexType> </xsd:element> <xsd: element name=="ch"> <xsd:attribute name="id" type="xsd:ID" use="required" /> </xsd:element>
Эта простая конструкция языка XML очень скоро перестала удовлетворять разработчиков документов XML. Им потребовалось ссылаться:
на определенную точку - букву, символ, позицию - внутри элемента;на множество точек, выбранных по образцу, скажем, на каждое появление в тексте слова "монитор";не на определенный элемент или точку внутри элемента, а на какую-то часть документа, границы которой не совпадают с началом и концом элемента;на что-нибудь вроде "третьего абзаца пятого параграфа предыдущей версии документа".
Кроме того, не всегда возможно расставлять в элементах атрибуты типа ID. В конце концов, документ не всегда доступен, или у разработчика просто может отсутствовать право записи в документ, на который надо сослаться.
Следуя духу XML, консорциум W3C создал для записи таких уточненных ссылок и меток язык XPointer. Общую структуру языка описывает рекомендация "XPointer Framework".
XPointer не является реализацией XML. Он не определяет никакие типы данных и не объявляет элементы и атрибуты. Он задает только правила записи меток и обращения к ним с помощью ссылок языка XLink.
На языке XPointer метки называются указателями. XPointer определяет два вида указателей: простые указатели и указатели, основанные на схеме. Рассмотрим подробнее каждый из этих видов.
Узлы дерева
Язык XPath различает семь видов узлов.
Узлы документа. Не отождествляйте узел документа с узлом корневого элемента документа. Узел корневого элемента вложен в узел документа наряду с узлами-комментариями и узлами инструкции по обработке. Кроме того, в языке XPath предусмотрена возможность работы с другими типами документов, возможно, содержащими несколько корневых элементов. Имя узла документа совпадает с именем корневого элемента документа. Узлы-элементы. Имя узла-элемента состоит из идентификатора пространства имен, получаемого по префиксу уточненного имени элемента, и локального имени элемента. Это расширенное имя узла. Если у элемента есть атрибут типа ID, то он служит идентификатором узла.Узлы-атрибуты. Их предок - узел-элемент, к которому относятся атрибуты, хотя они не считаются потомками этого узла. Узел-атрибут тоже определяется расширенным именем, полученным из уточненного имени атрибута.Узлы пространств имен. С каждым узлом-элементом связаны узлы тех пространств имен, в область действия которых входит данный элемент. Так же как и узлы-атрибуты, они не считаются потомками узла-элемента, хотя считают его своим предком. Поэтому программа-анализатор, обходя дерево, не будет автоматически просматривать узлы пространств имен. Имя узла пространства имен - это префикс, связанный с ним.Узлы инструкций по обработке. Это отдельные узлы, имена которых - это имена целевых приложений, выполняющих инструкцию. Первая строка пролога документа XML <?xml version="1.0"?> не считается инструкцией по обработке и не входит в дерево документа.Узлы комментарии. Каждый комментарий заносится в дерево как узел без имени.Текстовые узлы. Это строка символов, записанная в теле элемента между вложенными элементами. У текстовых узлов нет расширенного имени.
Узел любого вида можно представить строкой символов. Для каждого вида узла правила представления свои, они перечислены далее.
Строка, представляющая узел документа или узел-элемент, состоит из всех строк, представляющих его узлы-потомки текстового вида.Строка, представляющая узел-атрибут, содержит его значение.Строка, представляющая узел пространства имен, содержит его строку URI.Строка узла инструкции по обработке составлена из ее содержимого.Узел-комментарий и текстовый узел сами являются строками, причем начальные символы <!- и конечные символы -> комментария в строку не входят.
Важность проекта Information Set
Все эти информационные пункты и свойства практически идентичны модели DOM. Фактически все различные технологии, определенные консорциумом W3C для доступа к документам XML - XML DOM, XLink, XPath, XPointer, а также XSLT - являются производными от базовой структуры, описанной в спецификации XML Information Set. Чтобы извлечь максимум из предоставляемых этими технологиями функциональных возможностей, необходимо рассматривать документы XML не как потоки текстовой информации, а именно как описанные ранее объекты.
Несмотря на то, что стандарт подробно описывает соединения между объектами, он не определяет какой-либо конкретной реализации.
Чтобы использовать различные технологии, определенные консорциумом W3C для доступа к документам XML и манипулирования ими, сначала необходимо изучить определения консорциума W3C в спецификации Infoset. Как только вы перестанете считать документы XML текстом и начнете думать о них как о связанных информационных пунктах, вы обнаружите, что механизмы связывания и запросов для доступа к документам XML становятся очень естественными и интуитивными. В этих технологиях используются пункты информационного набора, описанные в стандарте Infoset; они позволяют манипулировать документами XML и адресовать их, используя представленные в пунктах связи типа "родитель-потомок" для навигации по этим документам.
Вычисляемый конструктор
Прямой конструктор использует заданные заранее имена элементов и атрибутов. Иногда это неудобно или невозможно сделать. В таких случаях применяют вычисляемые конструкторы.
Вычисляемые конструкторы могут создавать узлы четырех видов: узлы-элементы, узлы-атрибуты, корневые узлы документа или текстовые узлы. Поэтому в начале конструктора надо указать вид создаваемого узла одним из слов element, attribute, document или text. После этого слова в фигурных скобках записывается выражение, конструирующее узел. Для узла-элемента и узла-атрибута нужно еще записать его имя, которое тоже можно задать выражением.

<
Выражения, определяющие путь
Чаще всего выражение языка XPath показывает путь к определяемому участку документа XML, начинающийся в корневом узле документа или каком-то начальном узле. Такие выражения состоят из нескольких шагов поиска, выполняемых последовательно слева направо. Последовательность, полученная на предыдущем шаге, передается следующему шагу, который использует ее как исходный материал для поиска. Шаги в выражении разделены наклонными чертами. Например, выражение
/contract/section/paragraph
состоит из трех шагов поиска, содержащих имена элементов contract, section и paragraph. В результате вычисления первого шага этого выражения получится последовательность узлов, вложенных в узел документа contract. На втором шаге из этой последовательности выбираются узлы section, на третьем - узлы paragraph. В результате вычисления всего выражения получается последовательность узлов, состоящая из всех элементов paragraph, вложенных в элементы section, которые, в свою очередь, вложены в элементы contract.
В общем случае шаг поиска устроен гораздо сложнее. Язык XPath 2.0 различает два вида шагов поиска: шаг, направляемый осью поиска, и шаг, направляемый фильтром. После выполнения шага, направляемого осью, получается последовательность узлов, а после выполнения фильтра в последовательности кроме узлов могут встретиться атомарные значения.
XML Information Set
Проект The XML Information Set, или Infoset, - рабочий проект W3C описания различных фрагментов информации, составляющих правильно оформленный документ XML.
Целью проекта является создание общего словаря для описания содержания документов XML. Любой процессор XML, возвращающий информацию о содержании документа XML, будет описывать содержание в терминах данных информационных пунктов.
Декларация xsl:function
Элемент xsl:function позволяет описывать самые настоящие пользовательские функции. Имя функции записывается в обязательном атрибуте nаmе, (аргументы функции задаются элементами xsl:param, а тело функции - это конструктор последовательности, записанный в содержимом элементе xsl:function. Результатом функции будет последовательность, созданная конструктором. Тип функции можно указать необязательным атрибутом аs.
Имя функции - это уточненное имя типа QName, причем оно должно обязательно записываться с префиксом.
Все аргументы функции позиционные, следовательно, все элементы xsl:param должны быть записаны в начале тела функции и порядок их записи имеет значение при вызове функции. У аргументов функции не может быть значений по умолчанию, следовательно, элементы xsl:param должны быть пустыми и у них не должно быть атрибутов select. Например:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:usr="http://myexamples.com" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xsl: function name= " usr:sum " as="xsl:integer"> <xsl:param name="x" as="xsl:integer" /> <xsl:param name="y" as="xsl:integer" /> <xsl:value-of select="$x + $y" /> </xsl:function>
вызвать функцию можно в любом выражении подходящего типа, записав ее имя и аргументы в скобках. Например:
<хsl:value-of select="10 + 2 * usr:sum(2, 3)" />
Функция может вызываться рекурсивно.
Декларация xsl:import
Элемент xsl:import записывается очень просто:
<хsl:import href="адрес URI таблицы стилей" />
Его можно записать только непосредственно в корневом элементе xsl:stylesheet и только в самом начале таблицы стилей. Элементов xsl: import может быть несколько.
Процессор XSLT отыскивает таблицу стилей по указанному атрибутом href адресу и подставляет ее на место элемента xsl:import перед преобразованием.
Некоторые правила преобразования из таблиц, импортируемых элементами xsl:import, могут конфликтовать с правилами, импортированными из других таблиц или определенными в самой таблице стилей. В таком случае чаще всего применяются те правила, которые записаны последними. Поэтому порядок записи элементов xsl:import в таблицу стилей имеет большое значение.
Декларация xsl:include
Второй элемент, включающий внешние таблицы стилей в данную таблицу, - это элемент xsl:include. Он записывается точно так же, как элемент xsl:import, и оказывает такое же действие:
<xsl:include href="адрес URI таблицы стилей" />
Его можно записать не только непосредственно в корневом элементе xsl:stylesheet, но, в отличие от элемента xsl:import, в любом месте таблицы стилей. Второе отличие от элемента xsl:import заключается в том, что порядок записи элементов xsl:include в таблице стилей не имеет значения.
Декларация xsl:param
Элемент xsl:param записывается или непосредственно в элементе xsl:stylesheet, чтобы задать параметр преобразования, или в элементе xsl:template, чтобы задать параметр правила, или в элементе xsl:function как аргумент функции. У него один обязательный атрибут name, определяющий имя параметра. Кроме него, часто присутствует необязательный атрибут select, в котором записывается выражение для получения значения параметра:
<xsl:param name="pl" select="10 + 20" />
Если атрибут select отсутствует, то значение параметра берется из содержимого элемента, которым может быть конструктор последовательности узлов и атомарных значений:
<xsl:param name="p2">10</xsl:param>
Если отсутствует и атрибут select, и содержимое элемента, то параметр получает значение пустой строки.
Дли получении значения параметра надо записывать его имя со знаком доллара: $p1,$p2. Например:
<xsl:when test= "$p1=10 ">
Правила, определяющие область видимости параметров, такие же, как и у имен объектов, определенных декларацией xsl:variable.
Еще один необязательный атрибут as содержит желательный тип, к которому будет приведено значение параметра.
Наконец, последний атрибут required, принимающий значения yes или nо (по умолчанию), указывает обязательность параметра. Если параметр обязателен, required="yes", то элемент xsl:param должен быть пустым и не содержать атрибут select. В таком случае он получит определенное значение при вызове функции или элементом xsl:with-param при вызове шаблона.
Декларация xsl:template
Элемент xsl:template определяет шаблонное правило преобразования. Своим атрибутом match он задает образец для отбора узлов, подлежащих преобразованию, а в теле содержит конструктор последовательности узлов и атомарных значений, которая и будет результатом преобразования отобранных по образцу узлов.
<xsl: template match=" Образец" name="Имя">Конструктор</хsl:template>
Каждый из атрибутов match и name не обязателен, но хотя бы один из них должен присутствовать.
Атрибут match содержит образец для отбора преобразуемых узлов.
Атрибут name определяет имя шаблона. Имя шаблона - это обычное уточненное имя XML типа QName. Шаблон можно вызвать по имени элементом xsl:call-template, а если он не содержит атрибута match, то такой вызов обязателен, поскольку неизвестны узлы, к которым его надо применить, и он не будут применяться автоматически. Очень часто именованный шаблон содержит параметры, заданные элементами xsl:param, и вызывается с различным параметрами совсем как обычная функция.
У элемента xsl: template могут быть дополнительные атрибуты mode, as, priority.
Атрибут mode определяет режим обработки.
Атрибут as указывает желаемый тип результата (полученная последовательность будет приведена к этому типу).
Атрибут priority назначает правилу приоритет, который будет учитываться при отборе правил, применимых к некоторому узлу.
При вызове именованного шаблона элементов xsl:call-template атрибуты match, mode и priority игнарируются.
Если у именованного шаблона нет атрибута match, то у него не должно быть и атрибутов mode и priority, в них просто нет никакого смысла.
Декларация xsl:variable
Элемент xsl:variable определяет имя объекта. Оно записывается обязательным атрибутом name. Имя объекта должно быть уточненным именем XML типа QName. Кроме того, атрибутом select переменной можно задать сам объект, а атрибутом as определить тип объекта. Например:
<xsl:variable name="var1" select="count(//person)" as="xs:integer" />
Имя var1 будет хранить число элементов person. Объект может быть получен из содержимого элемента xsl: variable:
<xsl: variable name="var2">10</xsl:variable>
или создан конструктором последовательности:
<xsl:variable name="var3"> <xsl:value-of select="count (//person) " /> <xsl:variable>
Если объект не получен из атрибута select или содержимого элемента xsl: variable, то по умолчанию имя связывается с пустой строкой.
Для того чтобы получить объект, связанный с именем, определенным элементом xsl: variable, перед именем надо поставить знак доллара: $varl, $var2. При этом следует учитывать область действия имени.
Область действия имени простирается на весь элемент, в котором оно определено, начиная с места определения и включая вложенные элементы, если только в них не определено то же самое имя.
Имена, определенные непосредственно в корневом элементе xsl:stylesheet, называются глобальными именами, остальные - локальными именами.
Хотя слово "variable" и переводится с английского языка как "переменная", имя, созданное элементом xsl: variable - это не имя переменной, его значение нельзя изменить. Это только название некоторого объекта, которое удобно использовать в тех случаях, когда объект надо использовать во многих местах таблицы стилей, а его вычисление сложно или громоздко.
Динамические трансформации
В предыдущем разделе было описано представление одних и тех же данных различными способами, и при этом все участники требовали конкретных статических версий документов XML. Однако иногда возникает необходимость в более динамической трансформации. Например, в электронных таблицах часто в ответ на щелчок мышью на заголовке столбца требуется отсортировать данные. Для этого нужны более динамичные трансформации.
Любая трансформация, требующая действий пользователя или создающая интерактивные документы, может представлять собой задачу, совершенно не похожую на создание статических документов. В ходе динамических трансформаций часто приходится осуществлять обработку событий, требующую использования языка программирования.
Такие трансформации можно осуществлять и без помощи XSL, используя языки сценариев и модель DOM, а модель DOM можно применять в браузерах благодаря ее совместимости с языками JavaScript, Java, C++, Perl, Visual Basic или Python. Поэтому часто при осуществлении трансформаций обходятся только моделью DOM и языками сценариев (без XSL).
Функции id() и key()
Образец может начинаться с вызова функции id() или функции key(). Единственным аргументом функции id() служит уникальный идентификатор узла, т.е. значение его атрибута типа ID. Например, образцу id(@xref) соответствует узел-элемент, на идентификатор которого ссылается значение атрибута xref. Образцу id(<h12>) соответствует узел-элемент с идентификатором h12, а образцу id(<h12>)//street - его потомки street любого уровня вложенности.
Функция id(), работающая с атрибутами типа ID, подвержена всем ограничениям этого типа, а именно:
у элемента может быть только один атрибут типа ID, значит, можно cссылаться только на этот атрибут, не говоря уже о том, что такой атрибут может вообще отсутствовать:значение атрибута типа ID уникально, значит, нельзя обратиться сразу к нескольким элементам;значение атрибута типа ID может быть только именем типа Name, значит, не может быть числом, содержать пробелы и многие другие символы;схема, в которой определен тип ID атрибута, может оказаться недоступной для процессора XSLT и он не "узнает" тип атрибута;функция id() работает только с атрибутами, но не с элементами, их содержимым и прочими узлами дерева документа;для внесения новых перекрестных ссылок в документ XML надо его менять, вставляя атрибуты типа ID, что может быть нежелательно или невозможно.
Функция key() менее требовательна. Она снимает ограничения функции id(), обращаясь не к атрибуту элемента, находящегося в документе ХМL, а к атрибуту use специального элемента xsl:key, расположенного в таблице стилей. У нее два аргумента:
имя ключа, задаваемое строкой типа QName; это значение атрибута name элемента xsl:key, позволяющее выбрать нужный элемент xsl:key.значение ключа, представляющее собой выражение, в результате вычисления которого получается последовательность из одного или нескольких атомарных значений типа xdt:anyAtomicType.
Образец с функцией key() выглядит примерно так: key("addr", 230007)//street.
Элемент xsl:key определяет ключ и множество значений, а функция key() выбирает из этого множества те значения, что совпадают со вторым аргументом функции key(). Таким образом, при необходимости создания новых ссылок в исходном документе XML, его не надо изменить, достаточно добавить новые элементы xml:key в таблицу стилей.
Функции процессора XSL
Во-первых, процессор строит рощу, являющуюся внутренним представлением документа. Эта роща всегда имеет корневой элемент, представляющий собой весь документ XML, а не его элемент верхнего уровня. Ниже корневого элемента расположена вся иерархия узлов. Каждый узел типизирован. Например, он может быть предназначен для определения DTD, для схемы или для команды обработки. Если элемент содержит атрибуты, то у каждого элемента также имеется коллекция узлов атрибутов. Если элемент содержит данные, то в узел элемента вкладывается еще и соответствующие им узел. Таким образом, потомками узла элемента может быть коллекция узлов атрибутов и узел данных.Во-вторых, создает структуру для документа XSLT. Она также может представлять собой рощу, но может быть структурой любого типа, оптимизированной для обработки шаблонов и соответствия образцов.Затем каждый раз, встретив элемент <xsl: apply-templates>, формирует список узлов и продолжит работу с этим списком. Если элемент <xsl:apply-templates> содержит атрибут select, список узлов формируется на основе указанного запроса XPath. В противном случае список содержит все дочерние узлы.Каждый раз, встретив конструкцию <xsl: value-of>, процессор извлекает значение из исходного дерева, основываясь на выражении XPath ее атрибута select.Трансформация не ограничивается только трансляцией типа один-к-одному: она позволяет добавлять новое информационное содержание, добавлять и удалять элементы, а также осуществлять трансляции типа один-ко-многим.
Инструкции управления xsl:if, xsl:for-each, xsl:choose
Элемент xsl:if запускает конструктор последовательности, содержащийся в его теле, только если истинно выражение, записанное в обязательном и единственном атрибуте test:
<xsl:if test="$x > $у"> <xsl:value-of select="$x"o/> больше <xsl:value-of select="$y" /> </xsl:if>
У элемента xsl:for-each в обязательном и единственном атрибуте select записывается выражение, дающее в результате последовательность. Для каждого члена этой последовательности выполняется конструктор, содержащийся в теле элемента xsl:for-each. В результате получается цикл, выполняющийся столько раз, сколько элементов у последовательности, полученной в результате вычисления выражения атрибута select.
У элемента xsl:choose нет ни одного атрибута, но в его теле записывается один или несколько элементов xsl: when и один необязательный элемент xsl:otherwise:
<xsl:choose> <xsl when test="$day=l">Понедельник</xsl:when> <xsl when test="$day=2">Bторник</xsl:when> <xsl when test="$day=3">Cреда</xsl:when> <xsl when test="$day=4">Четверг</xsl:when> <xsl when test="$day=5">Пятница</xsl:when> <xsl when test="$day=6">Cyббота</xsl:when> <xsl when test="$day=7">Воскресенье</xsl:when> <xsl otherwise>Ошибка определения дня нeдeли</xsl:otherwise> </xsl:choose>
У элемента xsl:when есть только один обязательный параметр test, содержащий логическое выражение, и тело, содержащее конструктор последовательности.
Элемент xsl: otherwise не имеет атрибутов, у него есть только тело, содержащее конструктор последовательности.
В инструкции xsl: choose всегда выполняется не больше одного варианта, Варианты xsl:when просматриваются в порядке их написания в инструкции xsl:choose. Как только будет найден вариант с истинным значением выражения test, он будет выполнен, и результат этого варианта будет результатом всей инструкции. Варианты, следующие за ним по порядку, не рассматриваются. Если ни один вариант не подойдет, то результатом инструкции будет результат конструктора, записанного в элементе xsl:otherwise. Если элемента xsl:otherwise в инструкции нет, то результатом будет пустая строка.
Инструкция xsl:apply-templates
Элемент xsl:apply-templates, записываемый чаще всего внутри элемента xsl: template, в простейшем виде пуст:
<xsl:apply-templates />
Он предписывает обработать рекурсивно все узлы-потомки узлов, отобранных родительским элементом xsl:template.
У элемента xsl:apply-templates есть необязательные атрибуты select и mode.
Атрибут select, значением которого должно быть выражение, дающее последовательность узлов, ограничивает обработку только указанными в нем узлами.
Атрибут mode выбирает режим обработки из режимов, уже определенных в элементах xsl:template. Режим - это любое имя типа QName, но два режима предопределены. Это текущий режим, отмечаемый словом #current, и режим по умолчанию, принимаемый при отсутствии атрибута mode, или отмечаемый явно словом #default.
Содержимым элемента xsl: apply-templates могут служить элементы xsl:sort и xsl:with-param.
Инструкция xsl:for-each-group
Элемент xsl:for-each-group отбирает последовательность узлов и атомарных значений своим обязательным атрибутом select и группирует ее элементы по признаку, заданному выражением, записанным в атрибуте group-by. Этот признак называется ключом группы. Ключ группы вычисляется заново для каждого элемента последовательности. В результате исходная последовательность, отобранная атрибутом select, разбивается на несколько последовательностей. В следующем примере в одну группу собираются все узлы-элементы name с одинаковым значением атрибута surname:
<xsl:for-each-group select="name" group-by="@surname">
Выражение, являющееся значением атрибута group-by, может давать несколько ключей группы, и один узел может попасть сразу в несколько групп. Например:
<xsl:for-each-group select="name" group-by="(@second, @surname)">
Второй способ разбить последовательность на группы дает атрибут group-adjacent. Он собирает в группу все подряд идущие элементы последовательности с одинаковым значением ключа. Такой отбор возможен, если в атрибуте group-adjacent содержится только один ключ группы. Процессор XSLT следит за тем, чтобы значением атрибута group-adjacent был один и только один ключ группы.
Третий и четвертый способы применимы к последовательностям, состоящим только из узлов, без атомарных значений. Эти способы применяют атрибут group-starting-with или атрибут group-ending-with. Значением этих атрибутов может быть не любое выражение, а только образец. В одну группу собираются все подряд идущие узлы, первый (последний) из которых удовлетворяет образцу. Остальные узлы из этой группы не будут удовлетворять образцу. Если несколько подряд идущих элементов последовательности удовлетворяют образцу, то они попадут в разные группы.
Итак, группы узлов создаются одним из четырех атрибутов элемента xsl:for-each-group: group-by, group-adjacent, group-starting-with, group-ending-with. В каждом элементе xsl:for-each-group должен быть один и только один из этих атрибутов. Полученные группы существуют и могут использоваться только в содержимом элемента xsl:for-each-group. В теле элемента xsl:for-each-group записывается конструктор последовательности, который выполняется по одному разу для каждой группы.
Для удобства работы с группами в язык XSLT введены функции current-group() и current-group-key ().Их можно использовать только в теле элемента xsl:for-each-group. У обеих функций нет аргументов. Результатом функции current-group() будет последовательность- текущая группа, а результатом функции current-group-key() - значение ключа текущей группы.
Инструкция xsl:value-of
Элемент xsl:value-of вычисляет выражение, записанное в его обязательном атрибуте select, и преобразует его в строку. Например, выше мы определили имя объекта var2. Чтобы получить значение объекта var2, надо записать:
<xsl:value-of select="$var2" /></example>
Если в результате вычисления выражения получается последовательность, то процессор XSLT версии 1.0 выберет из нее только первый элемент, преобразованный в строку.
Элемент xsl:with-param
Элемент xsl:with-param ссылается на некоторый параметр, имя которого записано в обязательном атрибуте name. Необязательным атрибутом select можно задать выражение, результат вычисления которого будет новым значением параметра:
<xsl:with-param name="pl" select="100 * 20" />
Новое значение можно задать и в содержимом элемента:
<xsl:with-param name="pl">100</xsl:with-param>
Элемент xsl:with-param используется только в инструкциях xsl:apply-templates, xsl:apply-imports, xsl:call-template.
Элементы, объявленные в XSLT
Язык XSLT объявляет около полусотни элементов. Из них 17 элементов верхнего уровня, которые могут быть непосредственно вложены в корневой элемент xsl:stylesheet таблицы стилей. Они называются декларациями. Это элементы xsl: import, xsl: include, xsl: attribute-set, xsl:character-map, xsl:date-format, xsl:decimal-format, xsl:function, xsl:import-schema, xsl:key, xsl:namespace-alias, xsl:output, xsl:param, xsl:preserve-space, xsl:sort-key, xsl:strip-space, xsl:template, xsl:variable. Более того, все эти элементы, кроме xsl:param и xsl: variable, можно записывать только на верхнем уровне вложенности, непосредственно в корневом элементе xsl:stylesheet.
Кроме элементов верхнего уровня вложенности, в языке XSLT объявлено более тридцати элементов, которые можно записывать в теле элементов верхнего уровня. Наиболее часто применяются элементы xsl:apply-templates, xsl:value-of, xsl:copy-of, xsl:sort, xsl:text.
Из всех элементов XSLT не верхнего уровня вложенности выделяются инструкции. Не путайте инструкции XSLT и инструкции по обработке XML. Формально инструкции XSLT определяются как элементы, которые можно вставлять в конструктор последовательности. К инструкциям, в частности, относятся элементы, создающие узлы всех семи видов и последовательности узлов. Это элементы xsl:element, xsl:attribute, xsl:text, xsl:comment, xsl:processing-instruction, xsl:namespace, xsl:result-document, xsl:sequence.
Кроме них, инструкциями считаются элементы xsl:apply-templates, xsl: value-of, xsl: variable и др., всего более двадцати элементов. К инструкциям относятся как элементы, управляющие выбором правил преобразовании xsl:if, xsl:for-each, xsl:choose, так и элементы, копирующие узлы xsl:copy, xsl:copy-of.
Все элементы необязательны и могут располагаться в любом порядке, за одним исключением: декларации xsl:import, если они есть, должны быть записаны первыми.
Рассмотрим некоторые наиболее часто применяемые элементы XSLT.
Каким образом процессор XSL трансформирует исходный документ
Как уже отмечалось, язык XSLT работает не с синтаксисом документа, а с его моделью. Исходный формат и формат назначения являются приложениями XML и подлежащая структура в обоих случаях представляет собой дерево. Кроме того таблица стилей XSL - это документ XML, и потому она также может быть представлена в виде дерева. Итак, процессоры XSLT работают с тремя деревьями.
Язык XSLT является декларативным, т.е. вы определяете, как должен выглядеть результат, а не как он должен быть трансформирован; именно для выполнения этой работы нужен процессор XSL. Таблица стилей XSL состоит из шаблонов (templates), определяющих, каким образом каждый узел исходного дерева должен быть представлен в дереве результата. Процессор проходит по роще источника, начиная с корня, и ищет соответствующие шаблоны в дереве таблицы стилей. Обнаружив шаблон, он с помощью содержащихся в нем правил записывает абстрактное представление результата в дерево результата. Так он перемещается по документу узел за узлом (это определяется инструкцией XSLT <xsl:apply-template>) и ищет соответствия в таблице стилей. Если соответствующего шаблона не обнаруживается, он переходит к следующему. Можно сказать, что в таком случае он выполняет шаблон по умолчанию, который не приводит к результату на выходе. По завершении работы процессора дерево результата можно транслировать в документ XML, текст, документ HTML или в другую желаемую форму.
Теоретически события должны происходить в описанной последовательности. Однако в методах создания обработчиков XSLT используются различные вариации. Процессоры XSLT можно оптимизировать, а таблицы стилей не обязательно сохранять в виде рощи или древовидной структуры. Тем не менее описанный подход дает общее представление об их поведении.
Образцы (patterns)
Прежде чем сделать преобразование дерева документа XML, из него следует выбрать те узлы, которые подвергнутся тому или иному преобразованию, Их можно выбирать по имени, содержимому, атрибутам и другим признакам. Условия отбора узлов задаются образцом (pattern), записанным в виде одного или нескольких выражений языка XPath 2.0. Выражения, содержащиеся в образце, объединяются вертикальной чертой |, означающей, что выбираемый узел должен удовлетворять хотя бы одному выражению образца. Вместо вертикальной черты можно записывать слово union.
В образце можно записать не всякое выражение XPath, а только путь, каждый шаг которого определяется осью, причем допускаются только три оси: child (по умолчанию), // и attribute. Это означает, что, находясь в каком-то узле, мы можем "увидеть", кроме него самого, только его атрибуты и узлы-потомки. Обратите внимание на то, что явная запись оси descendant-or-self недопустима, применяется только сокращенная запись //. Запись оси attribute:: можно сократить до одной "собачки" @, а текущий узел очень часто обозначается точкой.
Хотя образец и строится как выражение языка XPath, но его цель - не отобрать последовательность узлов, а проверить соответствие узла данному образцу. Можно сказать, что некоторый узел Node соответствует некоторому образцу pattern тогда и только тогда, когда узел Node принадлежит последовательности узлов - результату вычисления выражения //Pattern. Например, образцу person//street будут соответствовать все узлы из последовательности //person//street, а именно все узлы street, вложенные в узлы-элементы person даже через несколько промежуточных узлов.
Надо сразу же отметить, что перечисленные ограничения касаются только образцов. В других конструкциях языка XSLT можно применять выражения XPath в полном объеме.
Причины трансформации XML
Документ XML, сохраненный в текстовом файле или сгенерированный программой, содержится в фиксированном формате. Хотя XML не зависит от платформы и может передаваться между различными частями приложения в некоторых случаях требуется информация из других структур. Кроме того, может потребоваться трансформировать динамически структуру документа в интерактивный документ, например для того, чтобы привести ее в соответствие запросам пользователя. В общем случае трансформации относятся к одной из трех категорий:
Структурные трансформации - трансформация одного словаря XML в другой по аналогии с переводом.
Создание динамических документов - таким способом пользователю предоставляется возможность изменять порядок, сортировать и фильтровать части документа XML, например щелчком на заголовке столбца таблицы изменить порядок ее содержания.
Трансформации в язык формирования изображения - подготовка документа для визуального представления в какой-либо форме браузера пользователя, например в Wireless Application Protocol (WAP), HTML, VOXML или в формате масштабируемой векторной графики.
Теперь рассмотрим эти три категории по очереди.
Различные браузеры
Многие Web-разработчики затратили огромные усилия и получили головную боль, пытаясь создать параллельные сайты или части сайтов для несовместимых версий браузеров. Мысль о том, что XML применим только в браузерах, понимающих этот язык, предполагает появление еще одной области несовместимости. Однако, разработав содержание сайта на языке XML, можно затем трансформировать его в другие языки разметки, чтобы из одного центрального содержания XML создать несколько версий документов HTML.
Трансформация документа таблицей стилей
Язык XSL является приложением XML, так что фактически таблица стилей (т.е. таблица трансформаций) представляет собой документ XML. В связи с этим документ может начинаться с декларации XML, показывающей анализатору, какой версией языка документ закодирован.
Корневым элементом нашей таблицы стилей является элемент <xsl: stylesheet>:
<xsl: stylesheet version=="1.0" xmlns:xsl=="http://www.w3.org/1999/XSL/Transform">.
Первым атрибутом этого элемента служит версия XSLT, вторым - атрибут xmlns:xsl, содержащий пространство имен для рекомендации трансформации XSL.
Этот атрибут декларирует пространство имен ХSLT. С данным пространством связан префикс xsl, так что корневым элементом фактически является элемент <stylesheet>, но он квалифицирован префиксом пространства имен xsl:. После объявления пространства имен любой элемент начинающийся с префикса xsl:, входит в состав словаря XSL.
Элемент <stylesheet> содержит три шаблона, каждый из которых вложен в элемент <template>. В таблице стилей этот элемент фактически называется <xsl:template>, так как мы включили пространство имен. У элемента <template> есть атрибут match, значением которого является образец (pattern) в форме выражения XPath. С ним сравнивается узел дерева, к которому применяется шаблон. Прежде всего процессору XSL надо сообщить желаемую форму вывода. Узнав ожидаемый формат вывода, процессор начнет исследовать исходный документ с корневого узла.
Трансформация документа XML с помощью модели DOM
Документ XML можно трансформировать и с помощью модели DOM, являющейся интерфейсом для представления документа в виде дерева. Однако такой способ трансформации документа является несколько рискованным, поскольку большинство реализации DOM содержит множество частных, свойственных только им конструкций. Например, даже в рекомендациях по DOM 2 не указано, каким образом загружать или сохранять документы XML, поэтому те, кто занимается их реализацией, должны изобретать свои методы для этих фундаментальных операций. В результате большинство сценариев, используемых для трансформации документов XML, не будут переносимыми, поскольку, как правило, содержат различные частные конструкции

<
Трансляция между различными словарями
Рассмотрим книжный каталог, размеченный на языке XML. Данные этого каталога можно использовать различными способами. Например, используя определение DTD, компания Wrox может разместить каталог на своем Web-сайте и в корпоративной сети Интранет. Книжные магазины требуют практически такую же информацию, что делает язык XML идеальным кандидатом для ее передачи. Однако, если разные книжные магазины используют для описания одних и тех же данных разные DTD, необходим способ трансформации наших данных в совместимую с ними версию.
Это только один пример ситуации, в которой возникает необходимость трансформации одного словаря XML в другой, и существует еще множество других. Такие трансформации считаются очень важными, например, в электронной коммерции, когда различные компании могут сохранять свои данные в разных форматах. Кроме того, при желании обновить одно из своих приложений вам придется трансформировать устаревший код XML в новую структуру.
Трансформации - ценное свойство в мире XML, особенно когда необходимо изменить назначение данных, размеченных на этом языке. Помимо прочего, если можно обойтись одной простой трансформацией, нет необходимости обслуживать две версии данных. Для таких трансформаций идеально подходят возможности, предлагаемые языком XSL.
XSL
Расширяемый язык таблиц стилей(XSL) основан на XML и предназначен для трансформации документа XML в другой документ XML или в объекты визуализации. Первоначальный язык XSL распался на три отдельных языка:
Язык трансформаций (XSLT)Язык визуализации (XSLF; он может использовать также и XSLT)Язык обращений к структуре, на которой основаны документы XML (XPath)
Язык XSL основан на каскадных таблицах стилей (Cascading Style Sheets, CSS) и на языке DSSSL (Document Style Semantics and Specification Language - язык спецификации и семантики стиля документа). По мере развития XSL его аспекты моделирования (работы со стилями) все ближе к CSS и отходят от DSSSL.
XSLT
XSLT является языком, для трансформации документов XML в другие документы XML. Для этого необходим процессор XSLT .
Язык XSLT написан на XML. Это означает, что обеспечивающая трансформацию документа XML таблица стилей XSLT является правильно оформленным документом XML. Прежде всего следует уяснить что обработчики XSLT работают не с документами, а со структурами.
Чтобы процессор XSLT смог трансформировать документ XML, последний должен сначала быть преобразован в структуру или во внутреннюю модель. Эта внутренняя модель представляет собой дерево и не зависит от используемых для доступа к ней интерфейсов API. В мире SGML такая абстрактная модель называется рощей. Поскольку язык XML является подмножеством SGML, он наследует его основные концепции. Итак, роща представляет собой просто абстрактную древовидную структуру, не зависящую от интерфейсов API, используемых для доступа к объектам этой структуры или для манипуляции ими. Например, для доступа к роще консорциум W3C рекомендовал модель DOM. Поэтому DOM представляет собой API, а роща - абстрактную структуру. У рощи может быть несколько интерфейсов API или для разных языков могут быть разработаны различные интерфейсы.