2009-02-11 5 views
3

Je comprends comment traiter ce document (ci-dessous) avec XSLT de l'élément personne au plus à l'intérieur. Mais je me demandais si:XSLT - Récursif de travail vers l'extérieur

  1. S'il est possible de travailler à partir de l'élément le plus profond.
  2. À quoi cela ressemblerait étant donné mon exemple.
<?xml version="1.0" encoding="utf-8" ?> 
<container> 
    <person name="Larry"> 
    <person name="Moe"> 
     <person name="Curly"> 
     <person name="Shemp"> 

     </person> 
     </person> 
    </person> 
    </person> 
</container> 
+0

@Bruno Tyndall J'ai testé cette transformation avec .NET 2.0 + XslCompiledTransform. Cela devrait aussi fonctionner avec XslTransform plus ancien. –

Répondre

2

Voici la manière la plus générale d'effectuer une "récursivité vers l'arrière" qui ne dépend pas de ce problème spécifique et qui peut être utilisée pour une grande variété de problèmes.

Cette transformation:

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

    <xsl:template match="/"> 
     <xsl:call-template name="backwardsRecursion"> 
     <xsl:with-param name="pList" select="//person"/> 
     </xsl:call-template> 
    </xsl:template> 

    <xsl:template name="backwardsRecursion"> 
     <xsl:param name="pList"/> 

     <xsl:if test="$pList"> 
     <xsl:apply-templates select="$pList[last()]"/> 

     <xsl:call-template name="backwardsRecursion"> 
      <xsl:with-param name="pList" select= 
      "$pList[position() &lt; last()]"/> 
     </xsl:call-template> 
     </xsl:if> 
    </xsl:template> 

    <xsl:template match="person"> 
     <xsl:value-of select="concat(@name,'&#xA;')"/> 
    </xsl:template> 
</xsl:stylesheet> 

lorsqu'il est appliqué sur le document XML initialement fourni, produit le résultat recherché:

Shemp 
Curly 
Moe 
Larry 

Prenez note, qu'un modèle générique nommé "backwardsRecursion" est appelé, qui implémente vraiment la récursion arrière. Ce modèle ne sait rien des nœuds qu'il traite, ni comment ils seront traités.

Ainsi, ce modèle peut être utilisé dans toutes les situations où un traitement récursif vers l'arrière est nécessaire.

+0

+1. Je vais devoir tester cette stratégie dans mon application .NET demain. Je pense que le processeur .NET XSLT devrait gérer toutes ces balises. – BuddyJoe

+0

@Bruno Tyndall J'ai testé cette transformation avec .NET 2.0 + XslCompiledTransform. Cela devrait aussi fonctionner avec XslTransform plus ancien. –

11

Vous pouvez utiliser le parent :: axe pour travailler vers le haut.

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="/"> 
     <xsl:apply-templates select="//person[not(person)]"/> 
    </xsl:template> 
    <xsl:template match="person"> 
    <xsl:value-of select="@name"/> -&gt; <xsl:apply-templates select="parent::person"/> 
    </xsl:template> 
</xsl:stylesheet> 

Non testé, je suis peut-être hors-syntaxe.

Il faut imprimer Shemp -> Spirales -> Moe -> Larry

+0

+1 semble très bien fonctionner. –

+0

Ne vaut +1 que pour "// person [not (person)]". :-) –

1

Une solution similaire à celle de Teun, mais permettant "personne" éléments dans pas immédiat relation parent-enfant est le suivant:

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

    <xsl:template match="/"> 
     <xsl:apply-templates select="//person[not(person)]"/> 
    </xsl:template> 

    <xsl:template match="person" name="tPerson"> 
     <xsl:value-of select="concat(@name,'&#xA;')"/> 

     <xsl:apply-templates select= 
      "ancestor::person[1]"/> 
    </xsl:template> 
</xsl:stylesheet> 

Lorsqu'il est appliqué sur le document XML fourni à l'origine, le résultat correct est produit:

Shemp

Curly

Moe

Larry

Il est bon de savoir que de nombreux problèmes de ce type ne nécessitent pas récursion du tout! Cette transformation produit exactement le même résultat et implique que l'itération:

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

    <xsl:template match="/"> 
     <xsl:for-each select="//person[not(person)]"> 
      <xsl:for-each select="ancestor::person | ."> 
      <xsl:sort select="position()" order="descending"/> 
       <xsl:value-of select="concat(@name,'&#xA;')"/> 
      </xsl:for-each> 
     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

Prenez note le genre qui assure l'ordre inverse du traitement.