Алексей Валиков - Технология XSLT
Результат следующего преобразования в точности совпадает с результатом преобразования в предыдущем примере.
Листинг 4.25. Пользовательские данные в элементе верхнего уровня<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="input">
<input>
<a/>
<b/>
</input>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates
select="document('')/
xsl:stylesheet/xsl:template[@name='input']/input"/>
</xsl:template>
<xsl:template match="a">
<A/>
</xsl:template>
<xsl:template match="b">
<B/>
</xsl:template>
<xsl:template match="input">
<output>
<xsl:apply-templates/>
</output>
</xsl:template>
</xsl:stylesheet>
Хитрость заключается в том, что мы обрабатываем содержимое именованного шаблона, которое вполне может принадлежать нулевому пространству имен. Единственное, что следует иметь в виду — это то, что этот шаблон не должен конфликтовать с другими шаблонами.
В отличие от предыдущего варианта с преобразованием, включенным в документ, этот способ является гораздо более работоспособным. Минусом его является только то, что на вход все равно должен подаваться какой-нибудь XML-документ, даже если его содержимое и не обрабатывается.
Литеральные элементы результата
Как мы уже видели из множества примеров, преобразования состоят не только из элементов языка XSLT. Например, в шаблоне
<xsl:template match="b">
<В/>
</xsl:template>
элемент B не принадлежит пространству имен XSLT и, следовательно, не считается XSLT-элементом. Такие элементы называются литеральными элементами результата (англ. literal result elements).
Когда процессор выполняет шаблон, содержащий литеральные результирующие элементы, для них в результирующем документе создаются элементы с тем же расширенным именем и атрибутами, содержимым которых является результат выполнения содержимого литерального элемента в преобразовании.
Попросту говоря, литеральные элементы выводятся в результирующий документ без изменений; но их содержимое при этом все же выполняется.
ПримерВ предыдущем случае шаблон содержал пустой литеральный элемент B. При выполнении этого правила процессор просто создаст в результирующем документе элемент с тем же расширенным именем и пустым содержимым — то есть это будет его точная копия.
Теперь обратимся к случаю, когда один литеральный элемент будет включать другой:
<xsl:template match="a">
<A>
<B/>
</A>
</xsl:template>
При выполнении этого шаблона процессор создаст элемент A и включит в него обработанное содержимое — то есть элемент B. Результатом этого шаблона будет XML-фрагмент:
<А>
<В/>
</А>
Теперь попробуем включить в содержимое элемента инструкцию XSLT:
<xsl:template match="a">
<А>
<xsl:value-of select="." />
</A>
</xsl:template>
При выполнении этого шаблона процессор создаст результирующий элемент а и включит в него результат выполнения его содержимого, то есть элемента xsl:value-of. Этот элемент создаст текстовый узел ей строковым значением текущего узла контекста преобразования. Например, если бы мы обрабатывали этим шаблоном элемент а вида
<a href="http://www.xsltdev.ru">Visit our site!</a>
результатом выполнения был бы следующий элемент:
<A>Visit out site!</A>
При воссоздании литеральных элементов в результирующем документе, процессор копирует также все атрибуты и узлы пространств имен, которые ассоциируются с данным элементом. Например, результатом выполнения следующего шаблона:
<xsl:template match="a">
<A HREF="http://www.xsltdev.ru"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<xsl:value-of select="." />
</A>
</xsl: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 самого литерального элемента или элемента xsl:stylesheet.
Пример Листинг 4.26<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/XHTML">
<xsl:template match="/">
<p
xmlns:xslt="http://www.w3.org/1999/XSL/Transform"
xslt:exclude-result-prefixes="xhtml">
<xslt:value-of select="2 * 2"/>
</xsl:template>
</xsl:stylesheet>
Обратим внимание на следующие особенности этого преобразования.
□ В нем объявлено пространство имен с префиксом xhtml.
□ Литеральный элемент p содержит объявление пространства имен с префиксом xslt и URI http://www.w3.org/1999/XSL/Transform.
□ Литеральный элемент p содержит атрибут, xslt:exclude-result-prefixes, принадлежащий пространству имен XSLT.
Как ни странно, ни одно из этих объявлений не проникнет в выходящий документ, который будет иметь вид
4
Попробуем объяснить такой результат. Атрибут xslt:exclude-result-prefixes не был включен в результирующий элемент p, поскольку принадлежал пространству имен XSLT (отметим еще раз, что принадлежность эта определяется не префиксом, а значением URI). Далее, объявление пространства имен
xmlns:xslt="http://www.w3.org/1999/XSL/Transform"
которое содержалось в литеральном элементе p, не вошло в результат, потому что URI этого объявления совпадало с URI пространства имен XSLT. И, наконец, объявление пространства имен xhtml было исключено атрибутом exclude-result-prefixes.
Атрибуты языка XSLT в литеральных элементах
Мы упомянули о том, что литеральные элементы могут содержать атрибуты, принадлежащие пространству имен XSLT. В табл. 4.3 они перечислены вместе с краткими описаниями назначения.
Таблица 4.3. XSLT-атрибуты литеральных элементов
Атрибут Назначение xsl:version Указывает версию языка в случае использования упрощенного синтаксиса записи преобразований xsl:exclude-result-prefixes Перечисляет префиксы пространств имен, которые должны быть исключены в данном элементе xsl:extension-element-prefixes Перечисляет префиксы пространств имен, которые используются в элементах расширения xsl:use-attribute-sets Перечисляет названия именованных наборов атрибутов, которые следует включить в данный элемент на выходеШаблоны значений атрибутов
Во многих элементах XSLT в качестве значений атрибутов могут быть указаны специальные шаблоны, называемые шаблонами значений атрибутов (attribute value templates). Замечательное свойство этих шаблонов заключается в том, что вместо простых строковых значений в атрибутах можно использовать результаты вычисления выражений. Выражения в шаблонах значений атрибутов должны быть заключены в фигурные скобки ("{}"). Если процессор встретит внутри значения атрибута выражение в таких скобках, он должен будет вычислить это выражение и заменить его в атрибуте вместе с фигурными скобками на результат вычисления в строковом виде.
ПримерДовольно часто в практике программирования на XSLT встречается потребность создавать элементы с именами, которые заранее не известны, но могут быть вычислены в ходе выполнения преобразования. Представим себе документ
<mark-up type="b">This text should be marked bold.</mark-up>