XML TeX MathML
Темы:
XML как есть
Технология XSLT
Схемы данных
Программирование
Базы данных
Инструменты
Веб-сервисы
Мир стандартов
Приложения
Статьи

Создание уникальных идентификаторов средствами XSLT

Автор: Bob DuCharme, 03 октября 2001

Оригинал статьи: XML.com

Перевод: В.Ярошевич, 16 ноября 2001

Страницы: 1

Когда вы при помощи таблицы стилей XSLT преобразуете один XML-документ в другой, возможность добавлять уникальные значения ID к элементам в результирующем документе позволяет сильно упростить его использование различными приложениями. Добавление такого идентификатора может, например, превратить каждый элемент в уникальный адрес для гиперссылок.

Функция XSLT generate-id() генерирует уникальный идентификатор для узла, указанного в аргументе. Этот идентификатор начинается с латинской буквы, так что вы можете использовать его как значение атрибута XML ID. Например, следующая таблица стилей копирует XML-документ и добавляет атрибут uid ("unique ID") к каждому элементу chapter, sect1 и sect2. Здесь инструкция xsl:value-of в первом шаблоне таблицы стилей использует функцию generate-id(), чтобы сгенерировать значение этих атрибутов.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes"/>

  <xsl:template match="chapter | sect1 | sect2">
    <xsl:copy>
      <xsl:attribute name="uid">
        <xsl:value-of select="generate-id(.)"/>
      </xsl:attribute>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

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

</xsl:stylesheet>

При помощи этой таблицы стилей из такого XML-документа

<chapter>
<para>Then with expanded wings he steers his flight</para>
<figure><title>"Incumbent on the Dusky Air"</title>
<graphic fileref="pic1.jpg"/></figure>
<para>Aloft, incumbent on the dusky Air</para>
<sect1>
<para>That felt unusual weight, till on dry Land</para>
<figure><title>"He Lights"</title>
<graphic fileref="pic2.jpg"/></figure>
<para>He lights, if it were Land that ever burned</para>
<sect2>
<para>With solid, as the Lake with liquid fire</para>
<figure><title>"The Lake with Liquid Fire"</title>
<graphic fileref="pic3.jpg"/></figure>
</sect2>
</sect1>
</chapter>

можно получить такой:

<chapter uid="N134711680">
<para>Then with expanded wings he steers his flight</para>
<figure><title>"Incumbent on the Dusky Air"</title>
<graphic fileref="pic1.jpg"/></figure>
<para>Aloft, incumbent on the dusky Air</para>
<sect1 uid="N134683456">
<para>That felt unusual weight, till on dry Land</para>
<figure><title>"He Lights"</title>
<graphic fileref="pic2.jpg"/></figure>
<para>He lights, if it were Land that ever burned</para>
<sect2 uid="N134684064">
<para>With solid, as the Lake with liquid fire</para>
<figure><title>"The Lake with Liquid Fire"</title>
<graphic fileref="pic3.jpg"/></figure>
</sect2>
</sect1>
</chapter>

Ваш XSLT-процессор может генерировать различные значения с функцией generate-id(). Фактически, если вы запускаете такую же таблицу стилей с таким же документов на входе несколько раз, XSLT-процессор может каждый раз создавать значения идентификаторов, отличные от тех, что были сгенерированы во время первого прохода. Однако, если вы вызываете generate-id() более, чем один раз внутри одной таблицы стилей с одинаковым узлом в качестве аргумента, она каждый раз для этого узла сгенерирует одинаковые значения идентификатора. Так как уникальный идентификатор является популярным способом для организации гиперссылок, эта устойчивость функции generate-id() делает ее замечательным инструментом для решения подобных задач.

Например, мы можем копировать документ подобно тому, как это мы сделали выше, но при этом в начало результирующего документа добавить список всех иллюстраций (см. колонку "Transforming XML" на XML.com). Если же при этом предполагется, что конечный документ будет HTML-файлом, то мы можем использовать функцию generate-id для того, чтобы превратить каждую запись в таком списке иллюстраций в гиперссылку на элемент img в теле документа, непосредственно содержащим эту иллюстрацию:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     version="1.0">

  <xsl:output method="html"/>

  <xsl:template match="chapter">
    <html><body>

      <!-- Формирование списка названий изображений,
	в котором каждое название является ссылкой
	на изображение в теле документа. -->
      <b>Pictures:</b><br/>
      <xsl:for-each select="descendant::figure">
        <a href="#{generate-id(graphic)}">
        <xsl:value-of select="title"/></a><br/>
    </xsl:for-each>

    <xsl:apply-templates/>
    </body></html>
  </xsl:template>

  <xsl:template match="para">
    <p><xsl:apply-templates/></p>
  </xsl:template>

  <xsl:template match="graphic">
    <!-- Изображение и название в виде подписи, по центру. -->
    <center><a name="{generate-id(.)}"><img src="{@fileref}"/></a>
    <b><xsl:value-of select="../title"/></b></center>
  </xsl:template>

  <!-- Блокировка вывода названия изображения, 
	так как	оно уже добавлено в результирующее дерево
	в шаблоне, соответствующем "graphic". -->
  <xsl:template match="figure/title"/>

</xsl:stylesheet>

С исходным документом, приведеным выше, и этой таблицей стилей XSLT-процессор может создать следующий HTML-документ:

<html>
    <body>
        <b>Pictures:</b>
        <br>
        <a href="#N134691840">"Incumbent on the Dusky Air"</a>
        <br>
        <a href="#N134692416">"He Lights"</a>
        <br>
        <a href="#N134757920">"The Lake with Liquid Fire"</a>
        <br>
<p>Then with expanded wings he steers his flight</p>

<center>
            <a name="N134691840"><img src="pic1.jpg"></a>
            <b>"Incumbent on the Dusky Air"</b>
        </center>
<p>Aloft, incumbent on the dusky Air</p>

<p>That felt unusual weight, till on dry Land</p>

<center>
            <a name="N134692416"><img src="pic2.jpg"></a>
            <b>"He Lights"</b>
        </center>
<p>He lights, if it were Land that ever burned</p>

<p>With solid, as the Lake with liquid fire</p>

<center>
            <a name="N134757920"><img src="pic3.jpg"></a>

            <b>"The Lake with Liquid Fire"</b>
        </center>


</body>
</html>

(Для просмотра HTML-документа, вы должны использовать свои собственные файлы pic1.jpg, pic2.jpg и pic3.jpg.) В таблице стилей используется generate-id() дважды:

  • Инструкция xsl:for-each в шаблоне, соответствующем "chapter", добавляет значение title каждого элемента figure в результирующее дерево для формирования списка "Pictures:" в верхней части конечного документа. При этом содержание каждого из таких элементов title для создания ссылки на соответствующее изображение в теле документа размещается внутри HTML-элемента a. Непосредственно адрес ссылки указывается в атрибуте href каждого из таких элементов a. В нашем случае значение атрибута href начинается со знака "#" для обозначения того, что ссылка ведет на другой элемент a в самом документе, в котором значение атрибута name равно части строки после знака "#" в ссылке-источнике. Например, <a href="#a123"> указывает на элемент <a name="a123"> где-либо внутри документа.

    Вместо строки "a123", определяющей каждый адрес ссылки, эта таблица стилей использует функцию generate-id() для создания идентификатора. Так как узел элемента graphic подается ей в качестве аргумента, функция создает идентифицирующую строку для каждого из трех элементов graphic: "N134691840", "N134692416" и "N134757920".

  • Для создания ссылки-адресата шаблон, соответствующий "graphic", размещает каждый HTML-элемент img в результирующем дереве внутри элемента a. Значение атрибутов src элементов img устанавливается значением атрибутов fileref элементов graphic исходного дерева, а элементы a используют функцию generate-id() для создания значений их атрибутов name. Указание в качестве аргумента к функции "." экивавалентно указанию self::node(), то есть текущего узла. В нашем случае это эквивалентно непосредственному указанию элементу узла graphic. Таким образом XSLT-процессор генерирует значение идентификатора для каждого узла graphic. Это те же самые три узла, что ранее использовали созданные generate-id() идентификаторы для ссылок, поэтому будут созданы такие же три значения: "N134691840", "N134692416" и "N134757920". Когда этот HTML-файл будет отображен в браузере, каждая ссылка в списке "Pictures:" теперь будет соответствовать изображению в документе.

Подведем итог. Устойчивость в данном контексте функции generate-id() при обработке конкретного узла, даже если функция генерирует идентификатор для этого узла более чем один раз, является ключевой. Элементы graphic не имели идентификаторов в исходном документе; с помощью это функции, их эквивалент в результирующем документе имеет их, и другие элементы в этом документе используют эти идентификаторы для связи с ними.

О Raleigh О CompuTel Реклама на сайте Контакты
Рейтинг@Mail.ruliveinternet.ru