KnigaRead.com/

Алексей Валиков - Технология XSLT

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Алексей Валиков, "Технология XSLT" бесплатно, без регистрации.
Перейти на страницу:

Приведем простой пример сортировки имен и фамилий.

Рассмотрим пример.

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

<list>

 <person>

  <name>William</name>

  <surname>Gibson</surname>

 </person>

 <person>

  <name>William</name>

  <surname>Blake</surname>

 </person>

 <person>

  <name>John</name>

  <surname>Fowles</surname>

 </person>

</list>

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

<xsl:template match="list">

 <xsl:copy>

  <xsl:for-each select="person">

   <xsl:sort select="name" order="descending"/>

   <xsl:sort select="surname"/>

   <xsl:copy-of select="."/>

  </xsl:for-each>

 </xsl:copy>

</xsl:template>

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

<list>

 <person>

  <name>William</name>

  <surname>Blake</surname>

 </person>

 <person>

  <name>William</name>

  <surname>Gibson</surname>

 </person>

 <person>

  <name>John</name>

  <surname>Fowles</surname>

 </person>

</list>

К сожалению, сортировкой нельзя управлять динамически. Все атрибуты элемента xsl:sort должны обладать фиксированными значениями.

Псевдонимы пространств имен

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

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

<transform>

 <remove select="a"/>

 <replace select="b" with="B"/>

 <replace select="c" with="C"/>

</transform>

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

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

<xsl:stylesheet

 version="1.0"

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


 <xsl:template match="a"/>


 <xsl:template match="b">

  <xsl:element name="B">

   <xsl:apply-templates/>

  </xsl:element>

 </xsl:template>


 <xsl:template match="c">

  <xsl:element name="C">

   <xsl:apply-templates/>

  </xsl:element>

 </xsl:template>


 <xsl:template match="@*|node()">

  <xsl:copy>

   <xsl:apply-templates select="@*|node()"/>

  </xsl:copy>

 </xsl:template>


</xsl:stylesheet>

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

<xsl:template match="replace">

 <xsl:element name="xsl:template">

  <xsl:attribute name="match">

   <xsl:value-of select="@select"/>

  </xsl:attribute>

  <xsl:element name="xsl:element">

   <xsl:attribute name="name">

    <xsl:value-of select="@with"/>

   </xsl:attribute>

   <xsl:element name="xsl:apply-templates"/>

  </xsl:element>

 </xsl:element>

</xsl:template>

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

<xsl:template match="replace">

 <xsl:template match="{@select}">

  <xsl:element name="{@with}">

   <xsl:apply-templates/>

  </xsl:element>

 </xsl:template>

</xsl:template>

был бы некорректен. По этой причине нам пришлось генерировать все инструкции при помощи xsl:element и xsl:attribute, что сделало шаблон громоздким и малопонятным.

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

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

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

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

<xsl:namespace-alias

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

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

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

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

Пример

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

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

<xsl:stylesheet

 version="1.0"

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

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


 <xsl:namespace-alias

  stylesheet-prefix="axsl"

  result-prefix="xsl"/>


 <xsl:template match="replace">

  <axsl:template match="{@select}">

   <axsl:element name="{@with}">

    <axsl:apply-templates/>

   </axsl:element>

  </axsl:template>

 </xsl:template>


 <xsl:template match="remove">

  <axsl:template match="{@select}"/>

 </xsl:template>


 <xsl:template match="transform">

  <axsl:stylesheet version="1.0">

   <xsl:apply-templates/>

   <axsl:template match="@*|node()">

    <axsl:copy>

     <axsl:apply-templates select="@*|node()"/>

    </axsl:copy>

   </axsl:template>

  </axsl:stylesheet>

 </xsl:template>

</xsl:stylesheet>

В этом преобразовании элемент 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. Выходящее преобразование

<axsl:stylesheet

 version="1.0"

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

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


 <axsl:template match="a"/>


 <axsl:template match="b">

  <axsl:element name="B">

   <axsl:apply-templates/>

  </axsl:element>

 </axsl:template>


 <axsl:template match="c">

  <axsl:element name="C">

   <axsl:apply-templates/>

  </axsl:element>

 </axsl:template>


 <axsl:template match="@*|node()">

  <axsl:copy>

   <axsl:apply-templates select="@*|node()"/>

  </axsl:copy>

 </axsl:template>


</axsl:stylesheet>

В этом сгенерированном преобразовании элементы имеют префикс axsl, но при этом принадлежат пространству имен XSLT.

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

<xsl:namespace-alias

 stylesheet-prefix="a"

 result-prefix="#default"/>

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

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*