Extraction de titres avec niveaux d'imbrication


Considérons un livre au format XML dont la DTD serait :
<!ELEMENT livre (titre, chapitre+)>
<!ELEMENT chapitre (titre, (section+))>
<!ELEMENT titre (#PCDATA)>
<!ELEMENT section (titre, contenu-section)>
<!ELEMENT contenu-section (#PCDATA | section)*>

XML :
<livre>
    <titre>XSLT</titre>

     <chapitre>
        <titre>C'est quoi</titre>
        <section>
            <titre>XSLT : un langage de transformation d'arbres XML</titre>
            <contenu-section>
                 XSLT est un langage destiné à transformer un arbre XML en un autre arbre XML. Bla bla bla...
            </contenu-section>
        </section>
        <section>
            <titre>Modes d'utilisation : ligne de commande, navigateur, serveur</titre>
            <contenu-section>
                <section>
                    <titre>Processeurs en ligne de commande</titre>
                    <contenu-section>
                        Il s'agit de programmes appelés manuellement. Bla bla bla...
                    </contenu-section>
                </section>
                <section>
                    <titre>Navigateurs</titre>
                    <contenu-section>
                         Les différents navigateurs peuvent être dotés d'un processeur XSLT. Bla bla bla...
                    </contenu-section>
                </section>
                <section>
                    <titre>Serveurs</titre>
                    <contenu-section>
                        Ce mode peut être vu comme la combinaison des deux mode précédents Bla bla bla...
                    </contenu-section>
                </section>
            </contenu-section>
        </section>
        <section>
            <titre>Structure d'un document XSLT</titre>
            <contenu-section>
                <section>
                    <titre>Structure d'un document XSLT</titre>
                    <contenu-section>
                             Un document XSLT est composé d'éléments XML. Bla bla bla...
                     </contenu-section>
                </section>
                <section>
                    <titre>Repère</titre>
                    <contenu-section> Dans une feuille de style XSLT, bla bla bla...</contenu-section>
                </section>
            </contenu-section>
        </section>
        <section>
            <titre>Premier exemple : transformation de documents XML</titre>
            <contenu-section>Bla bla bla...</contenu-section>
        </section>
    </chapitre>
    <chapitre>
        <titre>Moteur XSLT</titre>
        <section>
            <titre>Étapes du processus</titre>
            <contenu-section>
                Lorsqu'un processeur XSLT est invoqué, plusieurs traitements sont effectués : bla bla bla.
             </contenu-section>
        </section>
        <section>
            <titre>Transformations</titre>
            <contenu-section>
                 Une fois construit l'arbre du document XML initial, le prcesseur considère bla bla bla...
             </contenu-section>
        </section>
    </chapitre>
    <chapitre>
        <titre>Elements du langage</titre>
        <section>
            <titre></titre>
            <contenu-section></contenu-section>
        </section>
    </chapitre>
    <chapitre>
        <titre>Autres exemples</titre>
        <section>
            <titre></titre>
            <contenu-section></contenu-section>
        </section>
    </chapitre>
    <chapitre>
        <titre>TODO : annexe - references</titre>
        <section>
            <titre></titre>
            <contenu-section></contenu-section>
        </section>
    </chapitre>
</livre>
Feuille XSL :
<xsl:template match="//titre[normalize-space(text()) != '']">
    <!-- le prédicat permet d'ignorer les titres vides -->
    <xsl:text>
    </xsl:text>
    <xsl:element name="titre">
        <xsl:attribute name="niveau">
            <!-- nombre d'éléments "titre" dans le chemin menant de la racine à l'élément courant -->
            <xsl:value-of select="count(ancestor::*/titre)"/>
        </xsl:attribute>
        <!-- intitulé du titre -->
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

<!-- patron qui empêche l'affichage des contenus de section (et tout autre noeud textuel) -->
<xsl:template match="text()"/>
Résultat :
<titre niveau="1">XSLT</titre>
<titre niveau="2">C'est quoi</titre>
<titre niveau="3">XSLT : un langage de transformation d'arbres XML</titre>
<titre niveau="3">Modes d'utilisation : ligne de commande, navigateur, serveur</titre>
<titre niveau="4">Processeurs en ligne de commande</titre>
<titre niveau="4">Navigateurs</titre>
<titre niveau="4">Serveurs</titre>
<titre niveau="3">Structure d'un document XSLT</titre>
<titre niveau="4">Structure d'un document XSLT</titre>
<titre niveau="4">Repère</titre>
<titre niveau="3">Premier exemple : transformation de documents XML</titre>
<titre niveau="2">Moteur XSLT</titre>
<titre niveau="3">Étapes du processus</titre>
<titre niveau="3">Transformations</titre>
<titre niveau="2">Elements du langage</titre>
<titre niveau="2">Autres exemples</titre>
<titre niveau="2">TODO : annexe - references</titre>

Précédent... ] Sommaire... ] [ Suivant... ]