KnigaRead.com/

Стивен Холзнер - XSLT

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Стивен Холзнер, "XSLT" бесплатно, без регистрации.
Перейти на страницу:

 </xsl:template>


 <xsl:template match="PLANETS">

  <xsl:apply-templates/>

 </xsl:template>


 <xsl:template match="PLANET">

  <TR>

   <TD><xsl:value-of select="NAME"/></TD>

   <TD><xsl:value-of select="MASS"/></TD>

   <TD><xsl:apply-templates match="RADIUS"/></TD>

   <TD><xsl:value-of select="DAY"/></TD>

  </TR>

 </xsl:template>


 <xsl:template match="RADIUS">

  <xsl:eval>milesToKilometers(this)</xsl:eval>

 </xsl:template>

</xsl:stylesheet>

Вот и все, результат этого преобразования приведен на рис. 5.4.

Рис. 5.4. Применение функции расширения в Internet Explorer


Со временем производители будут поставлять все больше и больше функций расширения. Как можно определить, доступна ли заданная функция расширения? Для этого служит функция function-available.

Применение функции function-available

Функция XSLT 1.0 function-available служит для проверки доступности функции. В следующем примере я хочу воспользоваться функцией расширения starpowder:calculate для математических вычислений, а если она недоступна, я отправляю в результирующий документ текст «Sorry, can't do math today.» (Извините, сегодня математические вычисления не работают.), хотя можно, конечно, прекратить обработку и вывести сообщение об ошибке при помощи элемента <xsl:message>:

<xsl:choose xmlns:starpowder="http://www.starpowder.com">

 <xsl:when test="function-available('starpowder:calculate')">

  <xsl:value-of select="starpowder:calculate('2+2')"/>

 </xsl:when>

 <xsl:otherwise>

  <xsl:text>Sorry, can't do math today.</xsl:text>

 </xsl:otherwise>

</xsl:choose>

Внешние объекты

В рабочем проекте XSLT 1.1 для поддержки функций расширения появился новый тип данных — внешний объект (external object). Переменной XSLT, о которой пойдет речь в главе 9, может быть присвоен внешний объект — так же, как и один из четырех типов данных XPath, поддерживаемых в XSLT (строка, число, логическое значение, набор узлов). Внешний объект представляет объект, который создается внешним языком программирования, возвращается функцией расширения и не может быть преобразован в один из четырех типов данных XPath. Тип данных «external object» был добавлен в XSLT для того, чтобы предоставить вам безопасную «оболочку» для таких данных. Пока еще никто не реализовал поддержку внешних объектов, но это ожидается в скором времени.

Элементы расширения

Элементы расширения — это элементы, добавленные в XSLT пользователем или производителем. В рабочем проекте XSLT 1.1 для элементов расширения был установлен ряд правил, и в XSLT 2.0 предполагается более широкая их поддержка. 

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

Для определения пространства имен расширений применяется атрибут extension-element-prefixes в элементе <xsl:stylesheet>, или атрибут xsl:extension-element-prefixes в элементе буквального результата или элементе расширения.

Ниже приведен пример. Xalan позволяет вам создать несколько выходных документов при помощи своего элемента расширения <redirect:write>. Для того чтобы применить этот элемент, я могу добавить в planets.xml элементу документа атрибут file, задав имя файла, в который будет отправлен вывод, как redirected.xml:

<?xml version="1.0"?>

<?xml-stylesheet type="text/xml" href="planets.xsl"?>

<PLANETS file="redirected.xml">

 <PLANET>

  <NAME>Mercury</NAME>

  <MASS UNITS="(Earth = 1)">.0553</MASS>

  <DAY UNITS="days">58.65</DAY>

  <RADIUS UNITS="miles">1516</RADIUS>

  <DENSITY UNITS="(Earth = 1)">.983</DENSITY>

  <DISTANCE UNITS="million miles">43.4</DISTANCE><!--B перигелии-->

 </PLANET>

 .

 .

 .

Теперь в таблице стилей XSLT, которую я назвал redirect.xsl, я определяю пространство имен «redirect» так, чтобы оно соответствовало классу Java, который поддерживает ее в Xalan: org.apache.xalan.lib.Redirect. Я также устанавливаю атрибут extension-element-prefixes элемента <xsl:stylesheet> в значение пространства имен «redirect»:

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

 version="1.0"

 xmlns:lxslt=http://xml.apache.org/xslt"

 xmlns:redirect="org.apache.xalan.lib.Redirect"

 extension-element-prefixes="redirect">

 .

 .

 .

В этот момент мне ничто не мешает применить элемент расширения <redirect:write> для записи вывода в новый файл (в отличие от указанного в командной строке). Например, для того, чтобы отправить в другой файл отформатированное содержимое элемента <PLANET>, я могу получить имя создаваемого файла из атрибута file элемента <PLANETS> и записать данные в этот новый файл:

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

 version="1.0"

 xmlns:lxslt="http://xml.apache.org/xslt"

 xmlns:redirect="org.apache.xalan.lib.Redirect"

 extension-element-prefixes="redirect">

 <lxslt:component prefix="redirect" elements="write open close" functions="">

  <lxslt:script lang="javaclass" src="org.apache.xalan.lib.Redirect"/>

 </lxslt:component>


 <xsl:output method="xml"/>


 <xsl:template match="/">

  <xsl:apply-templates/>

 </xsl:template>


 <xsl:template match="PLANETS">

  <redirect:write select="@file">

   <PLANETS>

    <xsl:apply-templates/>

   </PLANETS>

  </redirect:write>

 </xsl:template>


 <xsl:template match="@*|node()">

  <xsl:copy>

   <xsl:apply-templates select="@*|node()"/>

  </xsl:copy>

 </xsl:template>

</xsl:stylesheet>

Операция завершена; вот как это может выглядеть при использовании Xalan в Windows:

C:planets>java org.apache.xalan.xslt.Process -IN planets.xml -XSL redirect.xsl -OUT new.xml

При этом будет создан файл redirected.xml, который выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>

<PLANETS>

 <PLANET>

  <NAME>Mercury</NAME>

  <MASS UNITS="(Earth = 1)">.0553</MASS>

  <DAY UNITS="days">58.65</DAY>

  <RADIUS UNITS="miles">1516</RADIUS>

  <DENSITY UNITS="(Earth = 1)">.983</DENSITY>

  <DISTANCE UNITS="million miles">43.4</DISTANCE>

 </PLANET>

 <PLANET>

  <NAME>Venus</NAME>

  <MASS UNITS="(Earth = 1)">.815</MASS>

  <DAY UNITS="days">116.75</DAY>

  <RADIUS UNITS="miles">3716</RADIUS>

  <DENSITY UNITS="(Earth = 1)">.943</DENSITY>

  <DISTANCE UNITS="million miles">66.8</DISTANCE>

 </PLANET>

 .

 .

 .

Применение функции element-available

Для проверки доступности элемента служит функция XSLT 1.0 element-available. В следующем примере я проверяю наличие элемента с названием <starpowder:calculate>:

<xsl:choose xmlns:starpowder="http://www.starpowder.com">

 <xsl:when test="element-available('starpowder:calculate')">

  <starpowder:calculate xsl:extension-element-prefixes="starpowder"/>

 </xsl:when>

 <xsl:otherwise>

  <xsl:text>Sorry, can't do math today.</xsl:text>

 </xsl:otherwise>

</xsl:choose>

Есть еще один способ обработать случай отсутствия элемента расширения — элемент <xsl:fallback>.

Элемент <xsl:fallback>

При помощи элемента XSLT 1.0 <xsl:fallback> можно указать, что следует делать в случае отсутствия элемента расширения. Этот элемент заключается в элемент расширения и используется в случае его недоступности.

У элемента <xsl:fallback> нет атрибутов, он содержит тело шаблона.

В следующем примере я создам элемент <xsl:fallback> внутри элемента <redirect:write> из предыдущего примера. В случае отсутствия элемента <redirect:write> элемент <xsl:fallback> прекратит обработку и выдаст сообщение:

<xsl:stylesheet

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

 version="1.0"

 xmlns:lxslt="http://xml.apache.org/xslt"

 xmlns:redirect="org.apache.xalan.lib.Redirect"

 extension-element-prefixes="redirect">

 <lxslt:component prefix="redirect" elements="write open close" functions="">

  <lxslt:script lang="javaclass" src="org.apache.xalan.lib.Redirect"/>

 </lxslt:component>

 <xsl:output method="xml"/>

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*