W3C разрешил расширения двух видов, главным образом, потому, что они уже были приняты де-факто — функции расширения и элементы расширения. Хотя они пользуются популярностью, это весьма неясная область, поскольку различные производители представили разные способы их реализации.
В XSLT 1.0 проверить доступность функции расширения можно при помощи функции function-available, а доступность элемента расширения — при помощи функции element-available.
XSLT 2.0 готовится определить стандартные средства связывания XSLT с элементами расширения и, вероятно, они будут гораздо лучше проработаны, чем имеющиеся сейчас.
Давайте посмотрим на все это в работе. В следующих разделах мы рассмотрим и функции, и элементы расширения, начав с функций.
ИНИЦИАТИВА EXSLT
Теперь, после того, как механизмы расширения в рабочем проекте XSLT 1.1 были отложены до XSLT 2.0, роль других разнообразных попыток стандартизации расширений XSLT значительно повысилась. Познакомьтесь, например, с EXSLT на www.exslt.org. EXSLT — это инициатива открытого сообщества, работающего над стандартизацией расширений XSLT.
Функции расширения
В XSLT 1.0 W3C определил способ отделения функций расширения от встроенных функций, установив требование, чтобы для обращения к функциям расширения использовались имена с заданным пространством имен, как в starpowder:calculate(). В XSLT 1.0 также имеется функция function-available() для проверки наличия функции по ее имени.
В рабочем проекту XSLT 1.1 на функции расширения были наложены некоторые дополнительные ограничения:
• функции расширения должны работать как встроенные функции;
• для Java и ECMAScript должны быть реализованы привязки к языку;
• механизм должен позволять естественное расширение для поддержки других языков в будущем;
• для реализации переносимой привязки функции расширения для любого конкретного языка не должен быть нужен процессор;
• процессор, реализующий функции расширения для любого языка, чья привязка обеспечивается спецификацией XSLT, должен соответствовать этим языкам;
• должны быть разрешены как встроенные реализации функций расширения, так и внешние;
• в функции расширения должно быть возможно передавать аргументы всех типов данных XPath;
• функции расширения должны иметь возможность возвращать в качестве результата все типы данных XPath;
• функции расширения должны иметь возможность создавать и возвращать наборы узлов фрагментов XML;
• должна иметься возможность включать или импортировать функции расширения из другой таблицы стилей;
• при неоднозначности выбора реализации функции расширения процессор должен выдать ошибку и прекратить работу;
• процессор должен преобразовывать аргументы способом, согласованным со встроенными функциями;
• функции расширения должны быть способны вернуть объект любого типа основного языка;
• должна существовать возможность передать в функцию расширения объект любого типа основного языка.
Вплоть до недавнего времени процессоры XSLT полностью самостоятельно определяли способ реализации функций расширения. Например, в Saxon и Xalan существует возможность непосредственно выполнять код Java, если определить пространство имен, задающее класс Java в качестве последней части URI. Я поступил так в следующем случае, определив пространство имен Date, соответствующее классу Java Date:
<?xml version="1.0"?>
<xsclass="underline" stylesheet version="1.0"
xmlns:xsl=http://www.w3.org/1999/XSL/Transform
xmlns:Date="http://www.saxon.com/java/java.util.Date">
.
.
.
После этого я могу воспользоваться такими функциями класса Date Java, как toString и new, для того чтобы заключить текущую дату в элементы заголовка <Н1> HTML в выходном документе (листинг 5.14).
Листинг 5.14. Применение функций Date Java<?xml version="1.0"?>
<xsclass="underline" stylesheel version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:Date="http://www.saxon.com/java/java.util.Date">
<xsclass="underline" template match="/PLANETS">
<HTML>
<HEAD>
<TITLE>
The Planets Table
</TITLE>
</HEAD>
<BODY>
<H1>
The Planets Table
</H1>
<BR/>
<H1>
<xsclass="underline" value-of select="Date:toString(Date:new())"/>
</H1>
<TABLE BORDER="2">
<TD>Name</TD>
<TD>Mass</TD>
<TD>Radius</TD>
<TD>Day</TD>
<xsclass="underline" apply-templates/>
</TABLE>
</BODY>
</HTML>
</xsclass="underline" template>