Технология XSLT — страница 34 из 66

Любопытным фактом является то, что XML-документ, являющийся результатом выполнения XSLT-преобразования, может и сам быть XSLT- преобразованием. Иными словами, преобразования могут генерироваться другими преобразованиями. В некоторых случаях такая возможность будет очень полезна, например, входящий XML-документ может описывать преобразование, которое нужно сгенерировать.

Листинг 8.13. XML-документ, описывающий требуемое преобразование

Приведенный выше документ описывает преобразование, которое должно удалять из входящего документа элементы

а
, а элементы
b
и
c 
заменять элементами
B
и
C
соответственно. Такое преобразование может выглядеть следующим образом.

Листинг 8.14. Преобразование

 version="1.0"

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






Преобразование, генерирующее такой код, не представляет особой сложности. Например, шаблон для обработки элемента replace может иметь следующий вид:

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

был бы некорректен. По этой причине нам пришлось генерировать все инструкции при помощи

xsl:element
и
xsl:attribute
, что сделало шаблон громоздким и малопонятным.

Если внимательно рассмотреть проблему, то окажется, что она состоит в том, что мы хотим в преобразовании использовать элементы одного пространства имен так, как если бы они относились к другому пространству.

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

xsl:namespace-alias
.

Элемент xsl:namespace-alias

Синтаксическая конструкция этого элемента выглядит следующим образом:

stylesheet-prefiх="префикс" | "#default"

result-prefix="префикс" | "#default"/>

Элемент

xsl:namespace-alias
назначает пространству имен выходящего документа пространство имен, которое будет подменять его в преобразовании, иначе говоря — псевдоним.

Обязательный атрибут

result-prefix
указывает, какому пространству имен назначается псевдоним. Обязательный атрибут
stylesheet-prefix
указывает, какое пространство имен будет использоваться в качестве его псевдонима в преобразовании. Оба атрибута содержат префиксы пространств имен, которые, естественно, должны быть ранее объявлены в преобразовании.

Пример

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

Листинг 8.15. Преобразование, использующее псевдонимы пространств имен

 version="1.0"

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

 xmlns:axsl="http://www.w3.org/1999/XSL/Transform/Alias">


  stylesheet-prefix="axsl"

  result-prefix="xsl"/>




В этом преобразовании элемент

xsl:namespace-alias
указывает на то, что все элементы, принадлежащие в преобразовании пространству имен с URI

http://www.w3.org/1999/XSL/Transform/Alias

в выходящем документе должны принадлежать пространству имен с URI

http://www.w3.org/1999/XSL/Transform

то есть пространству имен XSLT.

Результатом применения этого преобразования к документу из листинга 8.13 будет следующий документ.

Листинг 8.16. Выходящее преобразование

 version="1.0"

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

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






В этом сгенерированном преобразовании элементы имеют префикс

axsl
, но при этом принадлежат пространству имен XSLT.

Атрибуты

stylesheet-prefix
и
result-prefix
элемента
xsl:namespace-alias
могут иметь значения
"#default"
. Определение вида

 stylesheet-prefix="a"

 result-prefix="#default"/>

означает, что элементы, принадлежащие в преобразовании пространству имен

а
, в выходящем документе должны принадлежать пространству имен по умолчанию. Определение вида

 stylesheet-prefix="#default"

 result-prefix="a"/>

означает, что элементы, принадлежащие в преобразовании пространству имен по умолчанию, в выходящем документе должны принадлежать пространству имен

а
.

Пример
Листинг 8.17. Преобразование

 version="1.0"

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

 xmlns:a="urn:a"

 xmlns="urn:b">


  stylesheet-prefix="#default"

  result-prefix="a"/>


  stylesheet-prefix="a"

  result-prefix="#default"/>



Листинг 8.18. Выходящий документ

Результатом этого преобразования является то, что пространство имен с URI

"urn:а"
стало пространством имен по умолчанию, а пространство имен с URI
"urn:b"
изменило префикс на
а
.

В преобразованиях можно объявлять несколько псевдонимов пространств имен при условии, что одно и то же пространство имен преобразования не должно быть объявлено элементами

xsl:namespace-alias
с одинаковым порядком импорта псевдонимом для различных пространств имен выходящего документа.

Пример

Если преобразование

a.xsl
содержит определение

 stylesheet-prefix="x"

 result-prefix="a"/>

а преобразование

b.xsl
— определение

 stylesheet-prefix="x"

 result-prefix="b"/>

где в обоих преобразованиях префикс

x
представляет одно пространство имен, а пространства имен
a
и
b
— разные, то преобразование
a.xsl
не сможет включать преобразование
b.xsl
и наоборот, потому что они будут иметь одинаковый порядок импорта и содержать элементы
xsl:namespace-alias
, назначающие разным пространствам имен одинаковые псевдонимы. В одном преобразовании такие псевдонимы также не имеют права встречаться. Если же подобное все же случилось, процессор может сигнализировать ошибку или использовать определение, которое было дано в преобразовании последним.

Совсем иначе обстоит дело с импортированием. При импортировании определения старших в порядке импорта преобразований могут переопределять определения младших преобразований. Таким образом, если преобразование

a.xsl
будет импортировать преобразование
b.xsl
, пространство имен
x
будет назначено псевдонимом пространству имен
а
и наоборот.

Ключи