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

  </output>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

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

<output>

 <A/>

 <B/>

</output>

Следует обратить внимание на следующие особенности этого примера.

□ Элементы верхнего уровня в обязательном порядке должны иметь ненулевое пространство имен. Поэтому мы включили элемент input и все его дочерние узлы в пространство имен urn:user. В листинге 4.23 эти элементы выделены полужирным шрифтом.

□ В шаблонах, которые обрабатывают элементы включенного документа, должны указываться паттерны, соответствующие расширенным именам этих элементов, то есть не input, a user:input.

□ Чтобы не выводить объявления пространств имен в выходящем документе, мы включили префикс user в атрибут exclude-result-prefixes элемента xsclass="underline" stylesheet.

Как можно видеть, включение элемента input как элемента верхнего уровня породило определенные проблемы. Для того чтобы избежать их, можно воспользоваться маленьким фокусом — включать документ не как элемент верхнего уровня, а в элемент верхнего уровня.

Пример

Результат следующего преобразования в точности совпадает с результатом преобразования в предыдущем примере.

Листинг 4.25. Пользовательские данные в элементе верхнего уровня

<xsclass="underline" stylesheet

 version="1.0"

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

 <xsclass="underline" template name="input">

  <input>

   <a/>

   <b/>

  </input>

 </xsclass="underline" template>

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

  <xsclass="underline" apply-templates

   select="document('')/

   xsclass="underline" stylesheet/xsclass="underline" template[@name='input']/input"/>

 </xsclass="underline" template>

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

  <A/>

 </xsclass="underline" template>

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

  <B/>

 </xsclass="underline" template>

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

  <output>

   <xsclass="underline" apply-templates/>

  </output>

 </xsclass="underline" template>

</xsclass="underline" stylesheet>

Хитрость заключается в том, что мы обрабатываем содержимое именованного шаблона, которое вполне может принадлежать нулевому пространству имен. Единственное, что следует иметь в виду — это то, что этот шаблон не должен конфликтовать с другими шаблонами.

В отличие от предыдущего варианта с преобразованием, включенным в документ, этот способ является гораздо более работоспособным. Минусом его является только то, что на вход все равно должен подаваться какой-нибудь XML-документ, даже если его содержимое и не обрабатывается.

Литеральные элементы результата

Как мы уже видели из множества примеров, преобразования состоят не только из элементов языка XSLT. Например, в шаблоне

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

 <В/>

</xsclass="underline" template>

элемент B не принадлежит пространству имен XSLT и, следовательно, не считается XSLT-элементом. Такие элементы называются литеральными элементами результата (англ. literal result elements).

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

Попросту говоря, литеральные элементы выводятся в результирующий документ без изменений; но их содержимое при этом все же выполняется.

Пример

В предыдущем случае шаблон содержал пустой литеральный элемент B. При выполнении этого правила процессор просто создаст в результирующем документе элемент с тем же расширенным именем и пустым содержимым — то есть это будет его точная копия.

Теперь обратимся к случаю, когда один литеральный элемент будет включать другой:

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

 <A>

  <B/>

 </A>

</xsclass="underline" template>

При выполнении этого шаблона процессор создаст элемент A и включит в него обработанное содержимое — то есть элемент B. Результатом этого шаблона будет XML-фрагмент:

<А>

 <В/>

</А>

Теперь попробуем включить в содержимое элемента инструкцию XSLT:

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

 <А>

  <xsclass="underline" value-of select="." />

 </A>

</xsclass="underline" template>

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

<a href="http://www.xsltdev.ru">Visit our site!</a>

результатом выполнения был бы следующий элемент:

<A>Visit out site!</A>

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

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

 <A HREF="http://www.xsltdev.ru"

  xmlns:xhtml="http://www.w3.org/1999/xhtml">

  <xsclass="underline" value-of select="." />

 </A>

</xsclass="underline" template>

будет элемент вида:

<A HREF="http://www.xsltdev.ru"

 xmlns:xhtml="http://www.w3.org/1999/xhtml">

 Visit out site!

</A>

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

□ Процессор не будет копировать атрибуты, принадлежащие пространству имен XSLT.

□ Процессор не будет создавать узел пространства имен, соответствующий URI http://www.w3.org/1999/XSL/Transform, то есть URI пространства имен XSLT.

□ Процессор не будет создавать узлы пространств имен, префиксы которых исключаются атрибутами exclude-result-prefixes самого литерального элемента или элемента xsclass="underline" stylesheet.

Пример