<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>
Пожалуй, самым элегантным решением этой задачи будет использование элемента расширения, который копировал бы в выходящий документ текущее время. Иначе говоря, при выполнении шаблона вида:
<xsl:template match='/'>
<!-- ... -->
<p>This page was generated at <ext:time/>.</p>
</xsl:template>
элемент расширения ext:time
должен быть заменен текущим временем. Ниже мы приведем пример реализации этого элемента для процессора Xalan.
Интерфейс программирования расширений в Xalan требует, чтобы для каждого элемента расширения был определен метод вида:
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
элемента xsl:stylesheet
:
<xsl:stylesheet
...
extension-element-prefixes='ext'>
...
</xsl:stylesheet>
В итоге наше преобразование будет иметь следующий вид.
<xsl:stylesheet
version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns:ext='xalan://de.fzi.xslt.ext'
extension-element-prefixes='ext'>
<xsl:template match='/'>
<!-- ... -->