2010-06-10 7 views
1

Essentiellement, je XML structuré comme celui-ci:XML récursive par XSLT XML

<A> 
<B> 
    <1>data</1> 
    <2>data</2> 
    <C> 
    <1>data</1> 
    <2>data</2> 
    <B> 
    <1>data</1> 
    <2>data</2> 
    <C> 
    <B> 
     <1>data</1> 
     <2>data</2> 
    </B> 
    </C> 
    </B> 
    <B> 
    <1>data</1> 
    <2>data</2> 
    </B> 
    </C> 
</B> 
</A> 

Je suis en train d'obtenir la sortie pour ressembler à ceci:

<A> 
<B 1="data" 2="data"> 
    <C 1="data" 2="data"> 
     <B 1="data" 2="data"> 
      <C> 
       <B 1="data" 2="data" > 
       </B> 
      </C> 
     </B> 
     <B 1="data" 2="data" > 
     </B> 
    </C> 
</B> 
</A> 

J'ai compris comment mettez tout en attributs et commencez à faire défiler les éléments. Le problème auquel je suis confronté est que lorsque vous essayez d'obtenir en dessous du premier C, rien ne se passe. Voici mon code:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"> 
    <xsl:output method="xml" indent="yes"/> 

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

    <xsl:template match="B"> 
     <xsl:for-each select="B"> 
      <B ItemID="{B/ItemID/text()}" ItemType="{ItemType/text()}" ItemSubType="{ItemSubType/text()}" 
        ItemTitle="{ItemTitle/text()}" ItemImage="{ItemImage/text()}" ItemImageOverride="{ItemImageOverride/text()}" 
       ItemLink="{ItemLink/text()}" ItemTarget="{ItemTarget/text()}>"> 
      <xsl:for-each select="C"> 
       <xsl:apply-templates select="C"/> 
      </xsl:for-each> 
      </B> 
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="C"> 
    <C ID="{ID/text()}" Title="{Title/text()}" Template="{Template/text()}" 
      Type="{Type/text()}" Link="{Link/text()}" ParentID="{ParentID/text()}" 
      AncestorID="{AncestorID/text()}" FolderID="{FolderID/text()}" Description="{Description/text()}" 
      Image="{Image/text()}" ImageOverride="{ImageOverride/text()}"> 
     <xsl:for-each select="B"> 
     <xsl:apply-templates select=".//B"/> 
     </xsl:for-each> 
    </C> 
    </xsl:template> 

</xsl:stylesheet> 
+0

votre document d'entrée n'est pas correct XML. Qname ne peut pas être "1" ou "2". Si cela était dans les nœuds de texte, vous devez également échapper "<" simbol avec sa référence d'entité "<". En fait, regardez comment le code-styler rend votre question. –

+0

Bonne question (+1). Voir ma réponse pour une solution complète et très simple/courte. –

Répondre

1

Dans l'esprit de XSLT: cette transformation:

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

<xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="a1|a2"> 
    <xsl:attribute name="{name()}"> 
    <xsl:value-of select="."/> 
    </xsl:attribute> 
</xsl:template> 
</xsl:stylesheet> 

lorsqu'il est appliqué sur le document XML corrigé de l'exemple de Alejandro:

<A> 
<B> 
    <a1>data</a1> 
    <a2>data</a2> 
    <C> 
    <a1>data</a1> 
    <a2>data</a2> 
    <B> 
    <a1>data</a1> 
    <a2>data</a2> 
    <C> 
    <B> 
     <a1>data</a1> 
     <a2>data</a2> 
    </B> 
    </C> 
    </B> 
    <B> 
    <a1>data</a1> 
    <a2>data</a2> 
    </B> 
    </C> 
</B> 
</A> 

produit désiré, la sortie correcte :

<A> 
    <B a1="data" a2="data"> 
     <C a1="data" a2="data"> 
     <B a1="data" a2="data"> 
      <C> 
       <B a1="data" a2="data"/> 
      </C> 
     </B> 
     <B a1="data" a2="data"/> 
     </C> 
    </B> 
</A> 
0
<xsl:apply-templates select=".//B"/> 

pourrait être un problème de l'OMI. vous devez probablement appeler le modèle.

// B signifierait Racine/B. Corrigez-moi si je me trompe.

1

Dans votre exemple, vous avez le chemin A/B/C/B/C/B/1 = données

<xsl:template match="C"> 
    # context() = A/B/C 
.. 
    <xsl:for-each select="B"> 
    # context() = A/B/C/B 
    # selects every B descendent of the current B 
    <xsl:apply-templates select=".//B"/> 
     # context() = A/B/C/B/C/B/ 
    </xsl:for-each> 
</xsl:template> 


<xsl:template match="B"> 
    # context() = A/B/C/B/C/B/ 
    <xsl:for-each select="B"> 
    # there are no B's under this B - only 1 and 2 so nothing selected 
    </xsl:for-each> 
</xsl:template> 

Vous semblez être l'imbrication supplémentaire pour-eachs et en sélectionnant plus profond que vous devez être. Avoir juste <xsl:apply-templates select="B|C"> dans votre template C pour traiter les Bs ou C directement imbriqués, et les mêmes dans votre template B. En ce moment, il sélectionne seulement Bs dans Bs dans Bs.