Как выполнить цикл с помощью XSLT через иерархические узлы?

Я пытаюсь пройти по узлам раздела Docbook. Их структура следующая:

<sect1>
   <sect2>
      <sect3>
         <sect4>
            <sect5>
            </sect5>
         </sect4>
      </sect3>
   </sect2>
</sect1>

Таким образом, внутри sect1 будет только sect2, в sect2 будет только sect3 и так далее. У нас также может быть несколько подузлов внутри узла; например, несколько sect2 внутри sect1.

Программно я бы перебирал их рекурсивно, используя счетчик для отслеживания того, в каком разделе находится цикл.

На этот раз я должен использовать XSLT и прокручивать его. Таким образом, есть ли эквивалентный способ или лучший способ сделать это в XSLT?

Редактировать: у меня уже есть аналогичный код, предложенный Вилли, где я указываю каждый узел секты (от sect1 до sect5). Я ищу решение, в котором он зацикливается, определяя узел секты сам по себе, и мне не придется повторять код. Я знаю, что спецификации Docbook допускают не более 5 вложенных узлов.


person Marcel    schedule 18.03.2009    source источник


Ответы (2)


Если вы выполняете одинаковую обработку для всех узлов sect{x}, независимо от {x}, как вы говорите в одном из комментариев, то достаточно следующего:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match=
     "sect1|sect2|sect3|sect4|sect5">
      <!-- Some processing here -->
      <xsl:apply-templates/>
    </xsl:template>
</xsl:stylesheet>

Если вам действительно нужно обработать таким же образом гораздо больше элементов, имеющих разные имена вида "sect"{x} (скажем, x находится в диапазоне [1, 100]), то можно использовать следующее:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match=
     "*[starts-with(name(), 'sect')
      and
        substring-after(name(), 'sect') >= 1
      and
        not(substring-after(name(), 'sect') > 101)
       ]">
      <!-- Some processing here -->
      <xsl:apply-templates/>
    </xsl:template>
</xsl:stylesheet>
person Dimitre Novatchev    schedule 18.03.2009

person    schedule
comment
Спасибо за ответ Вилли. У меня происходит что-то подобное, где я должен писать код для каждого раздела (от раздела 1 до раздела 5). Я знаю, что спецификации Docbook допускают только 5 узлов секты, но я искал что-то, где я мог бы определить номер секции на лету. - person Marcel; 18.03.2009
comment
Понимаю. Хм, не уверен навскидку. Разумные умы здесь, вероятно, расходятся, но сам я бы не стал использовать подход динамического определения номера раздела, потому что пять элементов на самом деле не совпадают. Что вы делаете внутри шаблонов? Он одинаков для каждого раздела? - person ; 18.03.2009
comment
Если шаблоны по существу одинаковы, вы можете сделать так, чтобы каждый шаблон sect_ вызывал шаблон с одним и тем же именем... - person ; 18.03.2009
comment
Я делаю то же самое для всех узлов sect1, поэтому я бы предпочел динамически определять номер раздела. Я думаю, подход с использованием шаблона sect_ может сработать; попробую это. - person Marcel; 18.03.2009
comment
Коррекция. Я делаю то же самое для всех узлов sect вместо всех узлов sect1. - person Marcel; 18.03.2009
comment
Как говорит Димитре, вы, безусловно, можете использовать | оператор для поддержки всех пяти. Не динамический, но спецификация фиксированная, поэтому неясно, будет ли динамический полезен. Я бы просто использовал одно шаблонное правило с пятью сектами или, объединенными вместе, и делал бы с ними все, что вы хотите. - person ; 18.03.2009
comment
Оператор | является оператором union, а не оператором "или" - person Dimitre Novatchev; 21.03.2009