Выбрать главу

<редкий>

 <рыболов>

  <может>

   <забыть>

    <как>

     <плавает>

      <щука/>

     </плавает>

    </как>

   </забыть>

  </может>

 </рыболов>

</редкий>

Напомним, что кодировка выходящего документа определяется атрибутом encoding элемента xsclass="underline" output и не зависит от кодировок преобразования и обрабатываемых документов. Например, можно легко создать преобразование, которое будет изменять кодировку входящего документа. Это будет идентичное преобразование с элементом xsclass="underline" output, определяющим целевой набор символов.

Листинг 8.60. Преобразование, изменяющее кодировку документа на KOI8-R

<xsclass="underline" stylesheet version="1.0"

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

 <xsclass="underline" output encoding="KOI8-R"/>

 <xsclass="underline" template match="@*|node()">

  <xsclass="underline" copy>

   <xsclass="underline" apply-templates select="@*|node()"/>

  </xsclass="underline" copy>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

Как можно видеть, XSLT довольно гибко поддерживает кодировки — входящие и выходящие документы, а также сами преобразования могут иметь разные наборы символов. Единственным ограничением является множество кодировок, поддерживаемое самим процессором, вернее парсером, который он использует для разбора входящих документов, и сериализатором, который служит для создания физического экземпляра выходящего документа.

Практически во всех процессорах поддерживаются кодировки UTF-8, US- ASCII и ISO-8859-1, но далеко не все могут работать с Windows-1251 или KOI8-R. Поэтому, создавая документы и преобразования в нестандартных кодировках, мы заведомо ограничиваем переносимость решений. В случаях, когда XML/XSLT приложения создаются под конкретный процессор с заведомо известными возможностями, это не является большой проблемой, однако в тех случаях, когда требуется универсальность или точно не известно, каким процессором будет производиться обработка, единственным выходом будет использовать UTF-8 — как во входящих документах, так и в самих преобразованиях.

Случай нескольких входящих документов

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

Функция document

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

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

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

<xsclass="underline" copy-of select="document('http://www.w3.org')"/>

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

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

<xsclass="underline" copy-of select="document('http://www.w3.org')/html/body/a"/>

скопирует все элементы а, находящиеся в теле (/html/body) внешнего документа.

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

Вызов document(string)

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

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

document('')

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

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

<xsclass="underline" stylesheet

 version="1.0"

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

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

 <user:data>

  <item>1</item>

  <item>2</item>

 </user:data>

 <xsclass="underline" variable

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

 <xsclass="underline" template match="/">

  <xsclass="underline" copy-of select="$data/item"/>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

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

<item

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

 xmlns:user="urn:user-namespace">1</item>

<item

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

 xmlns:user="urn:user-namespace">2</item>

Вызов 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)