2010-12-03 6 views
0

J'ai un fichier XML d'origine comme ça:Générer un nouvel arbre et assigner à une variable

<list> 
<no value="8"> 
    <no value="11"> 
     <no value="6"> 
      <no value="32"/> 
      <no value="56"/> 
     </no> 
     <no value="9"> 
      <no value="111"/> 
      <no value="67"/> 
     </no> 
    </no> 
    <no value="7"> 
     <no value="5"/> 
     <no value="11"/> 
    </no> 
</no> 

Et maintenant, je veux échanger la valeur d'attribut de nœud parent et ses nœuds enfants tels que:

<list> 
<no value="8"> 
    <no value="11"> 
     <no value="6"> 
      <no value="32"/> 
      <no value="56"/> 
     </no> 
     <no value="9"> 
      <no value="111"/> 
      <no value="67"/> 
     </no> 
    </no> 
    <no value="11"> 
     <no value="5"/> 
     <no value="7"/> 
    </no> 
</no> 

Et aussi je veux mettre cet arbre dans une variable qui serait utilisée comme source d'entrée pour un autre modèle. J'ai tendance à utiliser une récursivité pour échanger jusqu'à ce que je reçois la plus grande valeur pour la racine:

<list> 
<no value="111"> 
     <no value="..."> 
    ...... 
</no> 

Quelqu'un peut-il me donner une suggestion s'il vous plaît? merci d'avance

+0

Etes-vous limité à XSLT 1.0 ou pouvez-vous utiliser le 2.0? Dans la version 1.0, vous ne pouvez pas placer le résultat d'un modèle dans une variable sous la forme d'un ensemble de nœuds pour les modèles ultérieurs, sauf si vous utilisez une fonction d'extension de nœud. De toute façon, dites-nous en plus sur votre processeur XSLT. – LarsH

+0

S'il vous plaît, clarifiez. Voulez-vous pour chaque parent un attribut 'value' avec le maximum de self et de descendant? –

+0

Cette question est incomplète (ne pas préciser quelles sont les exigences pour le "swap" - lequel des nombreux (devrait-il toujours s'agir de deux enfants) atributes des enfants est choisi pour être permuté avec l'attribut paren'ts? complète * sortie XML souhaitée de la transformation? –

Répondre

0

Vous avez un étrange requeriment ... Dans un autre langage, des structures binaires sont utilisées avec un algorithme comme commande ou pour obtenir le maximum. Ce n'est pas vraiment nécessaire dans XSLT car il ne traite que des arbres et des arbres, donc il a beaucoup d'algorithmes intégrés comme le tri.

En outre, cela est une feuille de style de ce que je pense est votre transformation souhaitée:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="node()|@*"> 
     <xsl:param name="pReplace"/> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"> 
       <xsl:with-param name="pReplace" select="$pReplace"/> 
      </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="no[@value][descendant::no/@value]"> 
     <xsl:param name="pReplace" select="''"/> 
     <xsl:variable name="vSwaped" 
         select="descendant-or-self::no 
           [contains($pReplace, 
              concat(generate-id(), 
                '+'))]"/> 
     <xsl:variable name="vPosition" select="count($vSwaped)+1"/> 
     <xsl:variable name="vReplace"> 
      <xsl:for-each 
       select="(ancestor::no[$vSwaped]| 
         descendant-or-self::no)[@value]"> 
       <xsl:sort select="@value" 
          data-type="number" order="descending"/> 
       <xsl:if test="position()=$vPosition"> 
        <xsl:value-of select="concat(generate-id(),'+',@value)"/> 
       </xsl:if> 
      </xsl:for-each> 
     </xsl:variable> 
     <xsl:copy> 
      <xsl:apply-templates select="@*"/> 
      <xsl:attribute name="value"> 
       <xsl:value-of select="substring-after($vReplace,'+')"/> 
      </xsl:attribute> 
      <xsl:apply-templates select="node()"> 
       <xsl:with-param name="pReplace" 
           select="concat($pReplace, 
               substring-before($vReplace,'+'), 
               '+',generate-id(),'|')"/> 
      </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="no[@value][not(descendant::no/@value)]" name="find"> 
     <xsl:param name="pReplace" select="''"/> 
     <xsl:param name="pFind" select="generate-id()"/> 
     <xsl:variable name="vFound" 
         select="substring-before(
           substring-after(
            $pReplace, 
            concat($pFind,'+')), 
           '|')"/> 
     <xsl:choose> 
      <xsl:when test="$vFound!='' and $pFind != $vFound"> 
       <xsl:call-template name="find"> 
        <xsl:with-param name="pReplace" select="$pReplace"/> 
        <xsl:with-param name="pFind" select="$vFound"/> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:copy> 
        <xsl:apply-templates select="@*"/> 
        <xsl:attribute name="value"> 
         <xsl:value-of select="//no[generate-id()=$pFind] 
                /@value"/> 
        </xsl:attribute> 
        <xsl:apply-templates select="node()"/> 
       </xsl:copy> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet> 

Sortie:

<list> 
    <no value="111"> 
     <no value="67"> 
      <no value="56"> 
       <no value="32"></no> 
       <no value="6"></no> 
      </no> 
      <no value="11"> 
       <no value="8"></no> 
       <no value="9"></no> 
      </no> 
     </no> 
     <no value="11"> 
      <no value="5"></no> 
      <no value="7"></no> 
     </no> 
    </no> 
</list> 

Explication: Un parent prend maximun Nième de sa branche. N est défini comme le nombre de maximum déjà pris de sa branche, plus un. Si la branche a déjà pris le maximum, les ancêtres sont également pris en compte dans le calcul maximum. Les dernières feuilles suivent le chemin des remplacements pour trouver leur valeur. Cela ressemble plus à un mappage statique entre l'état d'entrée et l'état de sortie, sauf pour les dernières feuilles.

Aussi, notez que je suis en train d'utiliser un modèle très général, donc seulement no éléments avec value attributs sont pris en charge. Et il peut y avoir n'importe quel autre type d'éléments qu'ils seraient juste copiés.

Questions connexes