уже было сказано ранее, четвертое преобразование, вынесенное теперь в импортируемый модуль, при разрешении конфликтов шаблонов будет самым младшим вследствие того, что порядок его импорта меньше, чем у других преобразований. Сообщения процессора будут иметь вид
4 template matched ORA.
5 template matched b.
3 template matched a.
2 template matched b.
1 template matched b.
3 template matched c.
Кстати сказать, XSLT предоставляет возможность выполнять в преобразованиях импортированные шаблоны вместо тех, которые, по мнению процессора, лучше подходят. Подобно тому, как для применения шаблонных правил мы использовали элемент
xsl:apply-templates
, импортированные шаблоны могут быть вызваны элементом
xsl:apply-imports
.
Элемент xsl:apply-imports
Синтаксис этого элемента:
<xsl:apply-imports/>
Элемент
xsl:apply-imports
можно использовать в шаблонах для применения правил, которые были импортированы во внешних модулях, но затем переопределены шаблонами основного преобразования.
Пример
Предположим, что в преобразованиях часто используется шаблон, который заменяет элементы
home
ссылками на сайт http://www.xsltdev.ru:
<xsl:template match="home">
<а href="#">www.xsltdev.ru</a>
</xsl:template>
При необходимости этот шаблон может быть переопределен. К примеру, ссылка может выглядеть как
Visit <а href="#">www.xsltdev.ru</a>
Соответственно, шаблон будет иметь вид
<xsl:template match="home">
<xsl:text>Visit </xsl:text>
<a href="#">www.xsltdev.ru</a>
</xsl:template>
Можно заметить, что оба шаблона имеют общую часть, которая выводит гипертекстовую ссылку. Эта часть может быть вынесена во внешнее преобразование
home.xsl
.
Листинг 5.18. Преобразование home.xml
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="home">
<a href="#">www.xsltdev.ru</a>
</xsl:template>
</xsl:stylesheet>
Для
того чтобы использовать внешний шаблон, основное преобразование должно импортировать его при помощи
xsl:import
и применять посредством xsl:apply-imports.
Листинг 5.19. Основное преобразование base.xsl
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:import href="#"/>
<xsl:template match="home">
<xsl:text>Visit </xsl:text>
<xsl:apply-imports/>
</xsl:template>
</xsl:stylesheet>
Элемент
xsl:apply-imports
нельзя использовать в блоках
xsl:for-each
и при вычислении глобальных переменных. Дело в том, что при обработке
xsl:apply-imports
процессор применяет импортируемые правила в соответствии с текущим шаблоном. Текущий шаблон — это то самое правило, которое процессор выполняет при обработке элемента
xsl:apply-templates
. При вычислении глобальных переменных и обработке блоков
xsl:for-each
текущее правило становится пустым, и, соответственно, вызов
xsl:apply-imports
вызовет ошибку.
Элемент
xsl:apply-imports
применяет шаблоны точно так же, как и элемент
xsl:apply-templates
, но при этом он имеет две особенности.
□ Шаблоны, определенные в основном преобразовании, применяться не будут, поскольку
xsl:apply-imports
применяет только импортированные правила.
□ Элемент
xsl:apply-imports
применяет только те правила, режим (
mode
) которых совпадает с режимом текущего шаблона.
В текущей версии XSLT
xsl:apply-imports
не может вызывать импортированные именованные шаблоны.
Для того чтобы лучше понять, зачем нужна такая сложная схема импорта, проведем аналогию с объектно-ориентированным программированием. Если рассматривать правила преобразований как методы классов, то импорт преобразований будет ни чем иным, как наследованием — все методы (шаблоны) класса-потомка (импортируемого преобразования) будут доступны в классе-наследнике (импортирующем преобразовании). При этом класс-наследник может переопределить методы класса потомка (шаблоны основного преобразования имеют порядок импорта старше, чем шаблоны импортированного преобразования). В этой схеме использование элемента
xsl:apply-imports
будет равносильно вызову метода родительского класса вместо переопределенного метода класса потомка.