Технология XSLT — страница 39 из 66

ьких входящих документов

Базовая архитектура преобразования подразумевает один входящий документ. Несмотря на это, в преобразованиях можно использовать и обрабатывать информацию, хранящуюся в других, внешних документах. Доступ к этим документам можно получить при помощи функции

document
.

Функция document

Запись функции:

node-set document(object, node-set?)

Функция

document
позволяет обращаться к внешним документам по их URI, например

скопирует в выходящий документ содержимое главной страницы Консорциума W3.

Функция

document
возвращает множество узлов. В простейшем случае это множество будет состоять из корневого узла внешнего документа. Функцию
document
можно использовать в более сложных XPath-выражениях, например в выражениях фильтрации. Так функция

скопирует все элементы а, находящиеся в теле (

/html/body
) внешнего документа.

Базовый сценарий использования функции

document
очень прост: ей передается строка, содержащая URI внешнего ресурса, а результатом является множество узлов, состоящее из корня внешнего документа. Однако на этом возможности
document
не заканчиваются. Мы рассмотрим несколько вариантов вызова функции
document
с параметрами различного типа.

Вызов document(string)

В случае если функции

document
передана строка, возвращаемое множество будет состоять из корневого узла внешнего документа. URI этого документа как раз и сообщается строковым аргументом функции
document
.

Интересной особенностью является возможность передать пустую строку:

document('')

В этом случае

document
возвратит корневой узел самого преобразования. При помощи
document('')
можно получать доступ к информации, хранящейся в самом преобразовании (оно ведь тоже является ХМL-документом). К сожалению, перед обращением к документу не существует способа проверить его существование. Процессор может либо выдать ошибку, либо возвратить пустое множество.

Пример
Листинг 8.61. Преобразование

 version="1.0"

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

 xmlns:user="urn:user-namespace">


1

2


  name="data" select="document('')/xsl:stylesheet/user:data"/>


Листинг 8.62. Выходной документ

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

 xmlns:user="urn:user-namespace">1

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

 xmlns:user="urn:user-namespace">2

Вызов document(node-set)

Передавая функции

document
множество узлов, можно получить доступ к нескольким документам, URI которых являются строковыми значениями узлов множества. Это, в частности, позволяет обращаться к документам, URI которых указаны в узлах обрабатываемого документа. Например, в контексте элемента

<а href="http://www.w3.org">...

вполне корректным вызовом функции

document
будет
document (@href)
.

Выражение

@href
— здесь возвращает множество, состоящее из единственного узла атрибута. Его строковое значение (
"http://www.w3.org"
) будет использовано как URI внешнего документа. Результирующее множество узлов будет содержать единственный корневой узел документа, расположенного по адресу http://www.w3.org.

Приведем еще один пример. XPath-выражение

//a/@href
возвращает множество всех атрибутов
href
элементов
а
текущего документа. Тогда множество document(
//a/@href
) будет содержать корневые узлы всех документов, на которые ссылается посредством элементов а текущий документ.

Вызов document(string, node-set)

URI, которые передаются функции

document
, могут быть как абсолютными, так и относительными, например
document('doc.xml')
возвратит корень документа
doc.xml
, находящегося в том же каталоге, что и само преобразование.

Функция

document
позволяет менять "точку отсчета" относительных URI. Если в качестве второго аргумента функции document передано множество узлов, то относительные идентификаторы ресурсов будут отсчитываться от базового адреса первого (в порядке просмотра документа) узла этого множества.

Базовым URI узла дерева является:

□ если элемент или инструкция по обработке принадлежит внешней сущности, базовым URI соответствующего узла будет URI внешней сущности;

□ иначе базовым URI является URI документа;

□ базовым URI текстового узла, узла атрибута, комментария или пространства имен является базовый URI родительского элемента.

Поясним вышесказанное на примерах.

Конструкция

копирует в выходящий документ

doc.xml
, находящийся в одном каталоге вместе с преобразованием.

Несмотря на то, что в следующем определении

xsl:for-each
меняет контекст,
document('doc.xml')
все равно возвращает корень документа
doc.xml
, находящегося в одном с преобразованием каталоге:

В следующей конструкции

document('doc.xml', /)
копирует документ
a/doc.xml,
поскольку в качестве базового URI используется URI корня документа
a/data.xml
:

Того же самого эффекта можно достичь следующим образом:

В следующей конструкции за базовый URI опять принимается URI самого преобразования (вернее, его корневого узла):

Протестируем теперь все это вместе в одном преобразовании.

Листинг 8.63. Преобразование

 version="1.0"

 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">



Листинг 8.64. Документ doc.xml

doc.xml

Листинг 8.65. Документ a/doc.xml

a/doc.xml

Листинг 8.66. Выходящий документ

doc.xml

doc.xml

a/doc.xml

a/doc.xml

doc.xml

Вызов document(node-set, node-set)

Если функции

document
передаются два множества узлов, то вычисление результата можно описать примерно следующим образом:

□ каждый из узлов первого аргумента преобразуется в строковый вид;

□ для каждого из полученных значений выполняется вызов типа

document(string, node-set)
;

□ результирующие множества объединяются.

Иными словами,

document(node-set, node-set)
работает через
document(string, node-set)
точно так же, как
document(node-set)
работает через
document(string)
. Разница лишь в том, что в первом случае базовый URI будет изменен.

Другие дополнительные функции XSLT