KnigaRead.com/

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

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

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

режим будет пустым, значит шаблон для xhtml:а вызываться не будет. Для того чтобы применить его при помощи xsl:apply-templates, мы добавим в этот элемент атрибут mode:

<xsl:apply-templates

 select=".//xhtml:a[@href and not(xhtml:*)]"

 mode="links">

 <xsl:sort select="."/>

</xsl:apply-templates>

Разберем более подробно это определение. Данная инструкция будет применять шаблоны с режимом links к узлам, возвращаемым выражением ".//xhtml:a[@href and not (xhtml:*)]", отсортированным в алфавитном порядке своих строковых значений. Выражение ".//xhtml:a[@href and not(xhtml:*)]" возвращает всех потомков текущего узла (путь выборки ".//"), которые принадлежат пространству имен xhtml, являются элементами с именами а, (тест имени "xhtml:a"), при этом имеют атрибут href и не включают в себя другие элементы (предикат "[@href and not (xhtml:*)]").

Преобразование целиком будет иметь следующий вид.

Листинг 5.4. Преобразование, добавляющее перечень ссылок

<xsl:stylesheet

 version="1.0"

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

 xmlns:xhtml="http://www.w3.org/1999/xhtml"

 xmlns="http://www.w3.org/1999/xhtml">


 <xsl:template match="xhtml:body">

  <xsl:copy>

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

   <h1>Links found on this page:</h1>

   <xsl:apply-templates select=".//xhtml:a[@href and not (xhtml:*)]">

    <xsl:sort select="."/>

   </xsl:apply-templates>

  </xsl:copy>

 </xsl:template>


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

  <xsl:copy>

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

  </xsl:copy>

 </xsl:template>


 <xsl:template match="xhtml:a">

  <xsl:copy>

   <xsl:copy-of select="@href|text()"/>

  </xsl:copy>

  <br/>

  <xsl:text>&#xA;</xsl:text>

 </xsl:template>

</xsl:stylesheet>

Применив это преобразование, например, к главной странице Консорциума W3 (http://www.w3.org), мы получим ее точный дубликат, в конце которого будет приведен перечень всех найденных текстовых ссылок. Выходящий документ будет заканчиваться фрагментом вида:

<h1>Links found on this page:</h1>

<a href="Consortium/">About W3C</a><br/>

<a href="WAI/">Accessibility</a><br/>

<a href="Consortium/Activities">Activities</a><br/>

и так далее.

Заметим, что того же эффекта можно было добиться другими способами, например, при помощи именованных шаблонов или элемента xsl:for-each, однако применение режимов, пожалуй, является наиболее гибкой техникой.

Досадным ограничением режимов является то, что режим нельзя выбирать динамически. Атрибут mode обязан иметь фиксированное значение, то есть вызов вида:

<xsl:apply-templates mode="{$mode}"/>

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

Именованные шаблоны

Вместо того чтобы при помощи атрибута match указывать, какая часть входящего документа должна преобразовываться данным шаблоном, ему можно присвоить имя и вызывать в любой момент вне зависимости от контекста преобразования. Такие шаблоны очень схожи по принципу с процедурами в императивных языках программирования — они позволяют выносить часто используемые части преобразований, передавать им параметры и вызывать вне зависимости от того, что именно обрабатывается в данный момент.

Имя шаблонному правилу присваивается атрибутом name элемента xsl:template. После этого шаблону более необязательно иметь атрибут match, теперь он может быть вызван просто по имени. Два шаблона с одним порядком импорта не могут иметь одинаковых имен. Если же одинаковые имена имеют шаблоны различного порядка импорта, шаблоны старшего порядка переопределяют младшие шаблоны

Пример

При генерации HTML-страниц часто встречающейся задачей является создание элемента head. Элемент head, как правило, содержит несколько элементов meta, предоставляющих метаинформацию, элемент title, который определяет название страницы и элемент link, который связывает данную страницу с другими документами, например, с каскадными таблицами стилей (CSS).

Для того чтобы упростить процедуру генерации head, мы можем вынести ее в отдельный именованный шаблон.

Листинг 5.5. Именованный шаблон для генерации элемента head

<xsl:template name="head">

 <head>

  <meta name="keywords" content="XSLT, XPath, XML"/>

  <meta name="description"

   content="This site is dedicated to XSLT and Xpath."/>

  <title>XSLTdev.ru - XSLT developer resource</title>

  <link rel="stylesheet" type="text/css" href="style/main.css"/>

 </head>

</xsl:template>

Думается, этот шаблон не требует пояснений — он просто создает в входящем документе несколько элементов. Непонятным пока остается другое — как вызывать именованные шаблоны? Элемент xsl:apply-templates явно не подходит, поскольку именованные шаблоны не обязаны иметь атрибут match. Их выполнение производится элементом xsl:call-template.

Элемент xsl:call-template

Приведем синтаксис этого элемента:

<xsl:call-template

 name="имя">

 <!-- Содержимое: несколько элементов xsl:with-param -->

</xsl:call-template>

Обязательный атрибут name указывает имя шаблона, который вызывается этой инструкцией. Например, шаблон с именем "head", приведенный выше, может быть вызван следующим образом:

<xsl:call-template name="head"/>

Атрибут name при вызове обязан иметь фиксированное значение — точно так же, как и в случае с mode и xsl:apply-templates, динамика здесь не разрешена.

При вызове xsl:call-template не изменяет контекста преобразования. Фактически, вызов именованного шаблона эквивалентен замене в тексте преобразования элемента xsl:call-template на тело вызываемого шаблона.

Приведем пример.

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

<content>

 Just a few words...

</content>

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

<xsl:stylesheet

 version="1.0"

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


<xsl:template match="/">

 <html>

  <xsl:call-template name="head"/>

  <body><xsl:copy-of select="content/node()"/></body>

 </html>

</xsl:template>


<xsl:template name="head">

 <head>

  <meta name="keywords" content="XSLT, XPath, XML"/>

  <meta name="description"

   content="This site is dedicated to XSLT and Xpath."/>

  <title>XSLTdev.ru - XSLT developer resource</title>

  <link rel="stylesheet" type="text/css" href="style/main.css"/>

 </head>

</xsl:template>


</xsl:stylesheet>

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

<html>

 <head>

  <meta name="keywords" content="XSLT, XPath, XML">

  <meta name="description"

   content="This site is dedicated to XSLT and Xpath.">

  <title>XSLTdev.ru - XSLT developer resource</title>

  <link rel="stylesheet" type="text/css" href="style/main.css">

 </head>

 <body>Just a few words...</body>

</html>

Примечание

Несколько более эффективным способом использования в документе статических частей (как содержимое элемента head в приведенном примере) является хранение этих частей во внешних документах и вставка их в выходящий документ при помощи элемента xsl:copy-of и функции document.

В этом примере шаблон, обрабатывающий корневой элемент, фактически эквивалентен шаблону вида:

<xsl:template match="/">

 <html>

  <head>

   <meta name="keywords" content="XSLT, XPath, XML"/>

   <meta name="description"

    content="This site is dedicated to XSLT and Xpath."/>

   <title>XSLTdev.ru - XSLT developer resource</title>

   <link rel="stylesheet" type="text/css" href="style/main.css"/>

  </head>

  <body><xsl:value-of select="content"/></body>

 </html>

</xsl:template>

В принципе именованные шаблоны не обязаны иметь атрибут match, но он все же может быть определен. В этом случае шаблон можно будет применять как для обработки частей документов элементом xsl:apply-templates, так и вызывая его по имени элементом xsl:call-template.

Пример

Изменим объявление нашего шаблона head следующим образом:

<xsl:template name="head" match="head">

 ...

</xsl:template>

Теперь, если входящий документ будет иметь вид

<page>

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