Главная » XSLT » Преобразование атрибутов в элементы

0

Задача

Имеется документ, в котором информация закодирована в виде атрибутов, а нужно закодировать ее в элементах.

Решение

Эта задача будто специально предназначена для применения идиомы переоп­ределяемого копирования, с которой мы начали эту главу. В примере ниже все ат­рибуты преобразуются в элементы.

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

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="@*">

<xsl:element name="{local-name(.)}" namespace="{namespace-uri(..)}">

<xsl:value-of select="."/> </xsl:element> </xsl:template>

</xsl:stylesheet>

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

<xsl:template match="@*">

<xsl:variable name="namespace"> <xsl:choose>

<!– Взять пространство имен атрибута, если оно задано –> <xsl:when test="namespace-uri()">

<xsl:value-of select="namespace-uri()" /> </xsl:when>

<!– В противном случае взять пространство имен родителя –> <xsl:otherwise>

<xsl:value-of select="namespace-uri(..)" /> </xsl:otherwise> </xsl:choose> </xsl:variable>

<xsl:element name="{name()}" namespace="{$namespace}">

<xsl:value-of select="." /> </xsl:element> </xsl:template>

Часто при преобразовании атрибутов в элементы необходимо проявлять большую избирательность (см. примеры 8.2 – 8.4).

Пример 8.2. Входные данные

<people which="MeAndMyFriends">

<person firstname="Sal" lastname="Mangano" age="38" height="5.75"/> <person firstname="Mike" lastname="Palmieri" age="28" height="5.10"/> <person firstname="Vito" lastname="Palmieri" age="38" height="6.0"/> <person firstname="Vinny" lastname="Mari" age="37" height="5.8"/> </people>

Пример 8.3. Таблица стилей для преобразования только элементов person

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

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="person/@*">

<xsl:element name="{local-name(.)}" namespace="{namespace-uri(..)}">

<xsl:value-of select="."/> </xsl:element> </xsl:template>

</xsl:stylesheet>

Пример 8.4. Результат

<people which="MeAndMyFriends">

<person>

<firstname>Sal</firstname> <lastname>Mangano</lastname> <age>38</age> <height>5.75</height> </person>

<person>

<firstname>Mike</firstname> <lastname>Palmieri</lastname> <age>28</age> <height>5.10</height> </person>

<person>

<firstname>Vito</firstname> <lastname>Palmieri</lastname> <age>38</age> <height>6.0</height> </person>

<person>

<firstname>Vinny</firstname> <lastname>Mari</lastname> <age>37</age> <height>5.8</height> </person>

</people>

XSLT 2.0

В XSLT 2.0 решение можно сделать более компактным, но смысл рецепта не изменяется. Ниже мы заменили громоздкую конструкцию xsl:choose выраже­нием if языка XPath 2.0.

<xsl:template match="@*">

<xsl:variable name="namespace"

select="if (namespace-uri()) then namespace-uri()

else namespace-uri(..)"/> <xsl:element name="{name()}" namespace="{$namespace}">

<xsl:value-of select="." /> </xsl:element>

</xsl:template>

Обсуждение

В этом разделе и в рецепте 8.2 рассматриваются задачи, возникающие из-за того, что автор документа принял неудачное решение закодировать информацию в атри­бутах вместо элементов. Проблема выбора между этими вариантами – один из самых противоречивых аспектов проектирования структуры документов1. Эти примеры полезны, так как позволяют исправить то, что вы считаете чужой ошибкой.

Мангано Сэл  XSLT. Сборник рецептов. – М.: ДМК Пресс, СПБ.: БХВ-Петербург, 2008. – 864 с.: ил.

По теме:

  • Комментарии