Перечисление узлов

Функции name и local-name предоставляют возможности для работы с документом, имена элементов и атрибутов в котором заранее неизвестны. Например, если шаблон определён как:

<xsl:template match="*[starts-with(local-name(), 'чеб')]">
  ...
</xsl:template>

то обрабатываться им будут все элементы, локальные части имён которых начинаются на «чеб» (например, «чебуреки», «чебоксары», «чебурашка»).

Следующее преобразование демонстрирует, как при помощи функции local-name и ключей сосчитать количество элементов и атрибутов документа с различными именами.

Пример 11.4. Входящий документ

<foo bar="1">
  <bar foo="2"/>
  <bar bar="3"/>
  <foo foo="4">
    <bar bar="5"/>
    <bar foo="6"/>
  </foo>
</foo>

Пример 11.5. Преобразование

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

  <!-- Выводим информацию в текстовом виде -->
  <xsl:output method="text"/>

  <!--
   |   Создаём ключ, отображающий узлы атрибутов и элементов
   |   в их локальные части имён.
   +-->
  <xsl:key name="node" match="*" use="local-name()"/>
  <xsl:key name="node" match="@*" use="local-name()"/>

  <xsl:template match="*|@*">
    <xsl:variable name="name" select="local-name()"/>
    <!--
     |   Если узел является первым узлом группы (первым встретившимся
     |   узлом документа с данным именем), выводим информацию о
     |   количестве узлов в группе (количество узлов с таким же именем).
     +-->
    <xsl:if test="generate-id(.) = generate-id(key('node', $name))">
      <xsl:text>Node '</xsl:text>
      <xsl:value-of select="local-name()"/>
      <xsl:text>' found </xsl:text>
      <xsl:value-of select="count(key('node', $name))"/>
      <xsl:text> times.&#xA;</xsl:text>
    </xsl:if>
    <!-- Рекурсивно обрабатываем дочерний элемент и атрибуты -->
    <xsl:apply-templates select="*|@*"/>
  </xsl:template>

</xsl:stylesheet>

Пример 11.6. Выходящий документ

Node 'foo' found 5 times.
Node 'bar' found 7 times.