tags:

views:

521

answers:

2

I am trying to traverse Docbook section nodes. Their structure are as follows:

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

So sect1 only have sect2 inside, sect2 will only have sect3 inside, and so on. We can also have multiple sub nodes within a node; for instance multiple sect2 within a sect1.

Programatically I would iterate through them recursively using a counter for keeping track of which section the loop is at.

This time I have to use XSLT and to loop through it. Thus is there an equivalent way, or better way of doing this in XSLT?

Edit: I already have similar code as suggested by Willie, where I specify every sect node (sect1 to sect5). I am looking for solution where it loops determining the sect node by itself, and I won't have to repeat code. I am aware that Docbook specs only allows up to 5 nested nodes.

A: 
<xsl:template match="sect1">
    <!-- Do stuff -->
    <xsl:apply-templates />
</xsl:template>

<xsl:template match="sect2">
    <!-- Do stuff -->
    <xsl:apply-templates />
</xsl:template>

<xsl:template match="sect3">
    <!-- Do stuff -->
    <xsl:apply-templates />
</xsl:template>

<xsl:template match="sect4">
    <!-- Do stuff -->
    <xsl:apply-templates />
</xsl:template>

<xsl:template match="sect5">
    <!-- Do stuff -->
    <xsl:apply-templates />
</xsl:template>
Willie Wheeler
Thanks for the reply Willie. I have something similar going on, where I have to write code for every section (sect1 to sect5). I know that Docbook specs only allows 5 sect nodes, but I was looking for something where I can define the section number on the fly.
Marcel Tjandraatmadja
I see. Hm, not sure offhand. Reasonable minds will probably differ here, but myself I would not take the approach of defining the section number dynamically, because the five elements are not really "the same". What are you doing inside the templates? Is it the same for each section?
Willie Wheeler
If the template are essentially the same, you could have each sect_ template call the same named template...
Willie Wheeler
I am doing the same thing for all sect1 nodes, that is why I would prefer defining the section number dynamically. I think the sect_ template approach might work; will try that out.
Marcel Tjandraatmadja
Correction. I am doing the same to all sect nodes, instead of all sect1 nodes.
Marcel Tjandraatmadja
Like Dimitre says, you can certainly use the | operator to support all five. Not dynamic but the spec is fixed so it's not clear that dynamic would be useful. I'd just use a single template rule with the five sect's or'ed together, and do whatever common thing you want to them.
Willie Wheeler
The operator | is the *union* operator -- not the 'or' operator
Dimitre Novatchev
+4  A: 

If you are doing the same processing to all sect{x} nodes, regardles of {x}, as you say in one of the comments, then the following is sufficient:

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

If you really need to process in the same way many more elements having different names of the form "sect"{x} (let's say x is in the range [1, 100]), then the following can be used:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <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>
Dimitre Novatchev