<xsclass="underline" template match="@*|node()" mode="second">
<xsclass="underline" copy>
<xsclass="underline" apply-templates select="@*|node()" mode="second"/>
</xsclass="underline" copy>
</xsclass="underline" template>
<xsclass="underline" template match="b" mode="second">
<c>
<xsclass="underline" apply-templates select="@*|node()" mode="second"/>
</c>
</xsclass="underline" template>
<!-- Основное преобразование -->
<xsclass="underline" template match="/">
<!-- Присваиваем переменной а корень входящего документа -->
<xsclass="underline" variable name="a" select="/"/>
<!-- Выводим переменную a -->
<xsclass="underline" comment> a: </xsclass="underline" comment>
<xsclass="underline" copy-of select="$a"/>
<!-- Присваиваем переменной b результат обработки переменной a -->
<xsclass="underline" variable name="b">
<xsclass="underline" apply-templates select="$a" mode="first"/>
</xsclass="underline" variable>
<!-- Выводим переменную b -->
<xsclass="underline" comment> b: </xsclass="underline" comment>
<xsclass="underline" copy-of select="$b"/>
<!-- Присваиваем переменной с результат обработки переменной b -->
<xsclass="underline" variable name="c">
<xsclass="underline" apply-templates select="xalan:nodeset($b)" mode="second"/>
</xsclass="underline" variable>
<!-- Выводим переменную c -->
<xsclass="underline" comment> c: </xsclass="underline" comment>
<xsclass="underline" copy-of select="$c"/>
</xsclass="underline" template>
</xsclass="underline" stylesheet>
Ход этого преобразования лучше всего прокомментирует полученный результат.
<а>
<a>1</a>
<a>2</a>
</а>
<!-- а: -->
<а>
<a>1</a>
<a>2</a>
</а>
<!-- b:-->
<b>
<b>1</b>
<b>2</b>
</b>
<!-- с: -->
<с>
<c>1</c>
<c>2</c>
</с>
Элементы расширения
Другой, несколько реже используемой, но не менее мощной возможностью расширения XSLT являются элементы расширения. В отличие от обычных элементов, при выполнении преобразования элементы расширения не просто копируются в выходящее дерево. При их обработке процессор должен выполнить определенные действия. Например, многие XSLT-процессоры, написанные на Java, позволяют связывать элементы расширения с методами Java-классов.
Предположим, что при выполнении преобразования в выходящий документ нам необходимо включить информацию о том, когда документ был сгенерирован — добавить элемент вида:
<p>This page was generated at 10:23.</p>
Пожалуй, самым элегантным решением этой задачи будет использование элемента расширения, который копировал бы в выходящий документ текущее время. Иначе говоря, при выполнении шаблона вида:
<xsclass="underline" template match="/">
<!-- ... -->
<p>This page was generated at <ext:time/>.</p>
</xsclass="underline" template>
элемент расширения ext:time
должен быть заменен текущим временем. Ниже мы приведем пример реализации этого элемента для процессора Xalan.
Интерфейс программирования расширений в Xalan требует, чтобы для каждого элемента расширения был определен метод вида:
тип элемент(org.apache.xalan.extensions.XSLProcessorContext context,
org.apache.xalan.templates.ElemExtensionCall elem)
где тип
— тип возвращаемого значения, а элемент
— локальная часть имени элемента расширения. Поскольку мы создаем элемент с локальной частью имени time и строковым типом возвращаемых данных, прототип нашего метода будет выглядеть как:
public String time(XSLProcessorContext context,
ElemExtensionCall elem)
Два аргумента, которые передаются методу элемента расширения, описывают контекст преобразования (XSLProcessorContext
) и параметры вызова элемента расширения (ElemExtensionCall
). Чуть позже мы покажем, как можно использовать эти объекты для создания более функциональных элементов расширения; пока же продолжим с элементом ext:time
.
Следующим шагом мы создадим класс расширения ext.java
, в котором реализуем описанный выше метод time
.
package de.fzi.xslt;
import java.util.Date;
import java.text.SimpleDateFormat;
import org.apache.xalan.extensions.XSLProcessorContext;
import org.apache.xalan.templates.ElemExtensionCall;
public class ext {
public String time(XSLProcessorContext context,
ElemExtensionCall elem) {
SimpleDateFormat df = new SimpleDateFormat("HH:mm");
return df.format(new Date());
}
}
Равно как и в случае с функциями расширения, связующим звеном между элементами и Java-имплементацией их семантики служат пространства имен. В нашем случае класс de.fzi.xslt.ext
может быть связан с префиксом пространства имен ext
следующим объявлением:
xmlns:ext="xalan://de.fzi.xslt.ext"
Однако это еще не все. Для того чтобы элементы определенного пространства имен воспринимались процессором как элементы расширения, необходимо также явно указать префиксы этих пространств в атрибуте extension-element-prefixes
элемента xsclass="underline" stylesheet
:
<xsclass="underline" stylesheet
...
extension-element-prefixes="ext">
...
</xsclass="underline" stylesheet>
В итоге наше преобразование будет иметь следующий вид.
<xsclass="underline" stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="xalan://de.fzi.xslt.ext"
extension-element-prefixes="ext">
<xsclass="underline" template match="/">
<!-- ... -->
<p>This page was generated at <ext:time/>.</p>
</xsclass="underline" template>