Конвертирование атрибутов при помощи XSLT

Содержание

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

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

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

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

Проверка на атрибуты

Большинство шаблонов написано для выбора основанного на совпадении с элементами. Когда таблица стилей обрабатывает атрибуты, образец выбора шаблона обычно относится к элементу, как показано в Листинге 1 (все примеры данной статьи взяты из таблицы стилей DocBook-to-HTML):

Листинг 1. Обработка атрибута, относящегося к элементу

<xsl:template match="ulink">
    <a href="{@url}"><xsl:apply-templates/></a>
</xsl:template>

Этот шаблон преобразует элемент ulink и атрибут url, однако образец выбора срабатывает только для элемента ulink.

Совпадение с элементом имеет смысл, если атрибут является обязательным, другими словами, если он должен присутствовать. Однако, если атрибут является опциональным, может возникнуть необходимость в проверке его наличия перед генерированием кода. В некоторых случаях это можно проверить, указав условия в образце выбора, как показано в Листинге 2:

Листинг 2. Проверка на атрибут в образце выбора шаблона

<xsl:template match="emphasis[@type='bold']">
    <b><xsl:apply-templates/></b>
</xsl:template>

Выбор по атрибутам

Проверка на атрибуты не всегда возможна. Взгляните на разметку в DocBook для картинки – imagedata. Она имеет опциональные атрибуты width и depth, которые можно сохранить в HTML. Довольно сложно будет запрограммировать все возможные комбинации (imagedata[@width], imagedata[@depth] и imagedata[@width and @depth] – эти три шаблона только для двух атрибутов). Разумнее будет позволить обработчику пройти по узлам атрибутов и создать для них шаблоны, как показано в Листинге 3:

Листинг 3. Шаблоны с выбором атрибутов

<xsl:template match="imagedata">
    <img>
        <xsl:apply-templates select="@*"/>
    </img>
</xsl:template>

<xsl:template match="@width">
    <xsl:attribute name="width">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

<xsl:template match="@depth">
    <xsl:attribute name="height">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

<xsl:template match="@fileref">
    <xsl:attribute name="href">
        <xsl:value-of select="."/>
    </xsl:attribute>
</xsl:template>

Обратите внимание, что по умолчанию обработчик не проходит по узлам атрибута. Вам необходимо задать это условие явно при помощи атрибута select="@*".

Итак, двумя важными различиями между шаблонами с образцами выбора для элементов и атрибутов являются:

  • Атрибуты являются листьями. Конструкция xsl:apply-templates ничего не даст, так как у атрибутов нет потомков для обработки. Вместо нее следует использовать xsl:value-of.
  • Большинство атрибутов на входе являются также атрибутами на выходе. Для вставки атрибута в конечное дерево следует использовать тег xsl:attribute. Здесь следует быть осторожным, так как xsl:attribute должен появляться перед любым из других потомков. Другими словами, конструкция xsl:apply-templates должна идти перед любым текстом или дочерним элементом.

Шаблоны без ограничений

Использование образцов выбора для атрибутов предоставляет вам полную силу XSLT. В шаблонах нет ограничений на превращение одного атрибута в другой. Вы можете добавлять условия в образцы выбора или превращать атрибуты в элементы. В шаблоне из Листинга 4 определяется специальное правило для выбора fileref как атрибута тега videodata. Здесь вместо атрибута создается элемент.

Листинг 4. Образец выбора для атрибута с условием

<xsl:template match="videodata/@fileref">
    <param name="src" value="{.}"/>
</xsl:template>

Кроме этого, можно одновременно применять шаблоны и к атрибутам, и элементам при помощи инструкции select="@* | node()", как это показано в Листинге 5:

Листинг 5. Вызов шаблона для обработки элементов и атрибутов

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

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