2010-02-01 4 views
0

Je voudrais ajouter un noeud dans la feuille la plus à gauche, avec le nom donné. Par exemple,XSLT. Comment ajouter un noeud dans la feuille la plus à gauche, avec le prénom?

<root> 
    <aaa name="a"> 
    <aaa name="x"/> 
    </aaa> 
    <aaa name="b"> 
    <aaa name="y"> 
     <aaa name="z"/> 
    </aaa> 
    </aaa> 
    <aaa name="c"> 
    <aaa name="z"/> 
    </aaa> 
</root> 

Prénom = "z" et le nouveau nœud donné est <aaa name="w">. arbre Nouveau devrait être la forme suivante:

<root> 
    <aaa name="a"> 
    <aaa name="x"/> 
    </aaa> 
    <aaa name="b"> 
    <aaa name="y"> 
     <aaa name="z"> 
     <aaa name="w"/> 
     </aaa> 
    </aaa> 
    </aaa> 
    <aaa name="c"> 
    <aaa name="z"/> 
    </aaa> 
</root> 
+0

Votre arbre original a 2 nœuds avec 'name = 'z''. Comment dire lequel vous voulez ajouter le nouveau noeud? –

+0

"feuille la plus à gauche" – Alexander

Répondre

0

Vous pouvez commencer avec quelque chose comme ceci:

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

    <xsl:template match="/"> 
    <xsl:apply-templates /> 
    </xsl:template> 

    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     <xsl:if test="@name='z'"> 
     <aaa name="w"/> 
     </xsl:if> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 
2

Si par le plus à gauche que vous voulez dire le noeud « z » avec la plus grande profondeur, vous pouvez d'abord définir une variable de travailler sur la profondeur de la gauche plus « z », puis ajoutez le nœud « w » lorsque vous correspondez un nœud à une profondeur

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <!-- Work out depth of left most 'z' node --> 
    <xsl:variable name="LeftMost"> 
     <xsl:for-each select="//*[@name='z']"> 
     <xsl:sort select="count(ancestor::*)" order="descending"/> 
     <xsl:if test="position() = 1"> 
      <xsl:value-of select="count(ancestor::*)"/> 
     </xsl:if> 
     </xsl:for-each> 
    </xsl:variable> 
    <xsl:template match="/"> 
     <xsl:apply-templates/> 
    </xsl:template> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
     <xsl:if test="@name='z' and count(ancestor::*) = $LeftMost"> 
      <aaa name="w"/> 
     </xsl:if> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

avec cela, si vous aviez deux « z » nœuds en même la profondeur que vous obtiendriez avec les deux reçoivent un nœud «w».

Une approche alternative consiste à utiliser generate-id() pour obtenir l'ID du poing 'z' à la plus grande profondeur, puis ajouter le 'w' lorsque vous faites correspondre le noeud avec le même identifiant. Cela ne ferait qu'ajouter un nœud 'w' au premier nœud 'z' qu'il trouve à la plus grande profondeur.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:variable name="LeftMost"> 
     <xsl:for-each select="//*[@name='z']"> 
     <xsl:sort select="count(ancestor::*)" order="descending"/> 
      <xsl:if test="position() = 1"> 
       <xsl:value-of select="generate-id()"/> 
      </xsl:if> 
     </xsl:for-each> 
    </xsl:variable> 
    <xsl:template match="/"> 
     <xsl:apply-templates/> 
    </xsl:template> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
      <xsl:if test="@name='z' and generate-id() = $LeftMost"> 
       <aaa name="w"/> 
      </xsl:if> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 
+0

+1. BTW: Ceci est ligne par ligne * exactement * la solution que j'ai trouvé sans avoir lu votre message. – Tomalak

+1

Ah! Je viens de voir que j'ai mal compris ce que les moyens les plus à gauche. Pour obtenir la première occurrence du nœud, remplacez simplement 'ansestor' par 'previous' dans les exemples. –

2

Une variante de @Tim C's variable based approach impliquerait un <xsl:key> et l'axe précédent, comme celui-ci:

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
> 
    <xsl:key 
    name="kCountPreceding" match="aaa[@name='z']" 
    use="count(preceding::aaa[@name='z'])" 
    /> 
    <xsl:variable name="vLeftMostId" select=" 
    generate-id(key('kCountPreceding', 0))" 
    /> 

    <xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*" /> 
     <xsl:if test="generate-id() = $vLeftMostId"> 
     <aaa name="w" /> 
     </xsl:if> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

Inconvénient de cette approche est que les variables sont pas autorisées dans une expression de match. Cela signifie que ceci ne peut pas être rendu dynamique, le code match="aaa[@name='z']" de la clé doit être codé en dur.

0

Pourquoi n'utilisez-vous pas l'axe précédent?

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:template match="/"> 
    <xsl:apply-templates /> 
    </xsl:template> 
    <xsl:template match="*[@name='z' and not(preceding::*[@name='z'])]"> 
    <xsl:copy> 
     <xsl:copy-of select="@*"/> 
     <aaa name="w" /> 
     <xsl:apply-templates /> 
    </xsl:copy> 
    </xsl:template> 
    <xsl:template match="*"> 
    <xsl:copy> 
     <xsl:copy-of select="@*"/> 
     <xsl:apply-templates /> 
    </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

BTW, la feuille la plus à gauche est la première feuille dans l'ordre du document, n'est-ce pas?

<xsl:for-each select="/descendant::*[@name='z' and not(*)][1]"> 
    ... 
    <aaa name="w" /> 
    ... 
</xsl:for-each> 
+0

oui, la première feuille, avec le prénom – Alexander

0

la feuille est plus à gauche de la première feuille dans l'ordre du document, est-ce pas?

oui, la première feuille, avec le nom donné

+0

@Alexander: S'il vous plaît ne pas utiliser Stack Overflow comme un forum. La section inférieure est pour les réponses à votre question, pas pour les posts de suivi ou les commentaires. À moins que vous ne répondiez à votre propre question (ce qui conviendrait), utilisez la fonction de commentaire ou modifiez votre question pour ajouter des détails manquants. Veuillez supprimer ce post. – Tomalak

Questions connexes