2011-01-25 2 views
5

salut j'ai un document xml sitemap qui ressemble à cecopie de xslt sans enfants

<pagenode title="home" url="~/" fornavbar="true"> 
<pagenode title="admin" url="~/admin" fornavbar="false"> 
    <pagenode title="users" url="~/admin/users" fornavbar="false"/> 
    <pagenode title="events" url="~/admin/events" fornavbar="true"/> 
</pagenode> 
<pagenode title="catalog" url="~/catalog" fornavbar="true"/> 
<pagenode title="contact us" url="~/contactus" fornavbar="false"/> 
</pagenode> 

maintenant je veux récupérer un document XML pour la barre de navigation, qui comprend tous les pagenodes qui ont fornavbar = vrai. Comment cela peut-il être fait?

le plus proche, j'ai pu obtenir jusqu'à présent était le suivant:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:template match="pagenode[@fornavbar='true']"> 
    <xsl:copy-of select="."/> 
</xsl:template> 
</xsl:stylesheet> 

le problème est qui comprend tous les enfants de tout ce qui correspond comme navbar

Je veux seulement copier tous les attributs , tous les enfants

mais si je tente

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:template match="pagenode[@fornavbar='true']"> 
    <pagenode title="{@title}" url="{@url}"/> 
    <xsl:apply-templates/> 
</xsl:template> 
</xsl:stylesheet> 

alors j'ai 2 problèmes

  1. je pourrais taper chaque attribut séparément, et j'ai un assez grand nombre par page et theyre susceptibles de changer éventuellement
  2. il perd la hiérarchie. tout devient plat l'un après l'autre

J'apprécierais tous et n'importe quelle aide dans le sujet.

merci!

EDIT: sortie échantillon id aiment voir

<pagenode title="home" url="~/" fornavbar="true"> 
<pagenode title="events" url="~/admin/events" fornavbar="true"/> 
<pagenode title="catalog" url="~/catalog" fornavbar="true"/> 
</pagenode> 
+0

Bonne question, +1. Voir ma réponse pour une solution complète mais très courte qui exploite pleinement le motif de conception XSLT le plus fondamental. :) –

Répondre

2

vous pouvez itérer sur les attributs d'un nœud à l'aide xsl:foreach select="@*" cette façon, vous ne devez pas copier les attributs à la main. Si vous appelez xsl:apply-templates à l'intérieur de votre élément de page, vous devriez obtenir le résultat désiré.

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template match="pagenode[@fornavbar='true']"> 
     <pagenode> 
      <xsl:for-each select="@*"> 
       <xsl:attribute name="{name(.)}"><xsl:value-of select="."/></xsl:attribute> 
      </xsl:for-each> 
      <xsl:apply-templates/> 
     </pagenode> 
    </xsl:template> 
</xsl:stylesheet> 

fait

<?xml version="1.0"?> 
<pagenode title="home" url="~/" fornavbar="true"> 
    <pagenode title="events" url="~/admin/events" fornavbar="true"/> 
    <pagenode title="catalog" url="~/catalog" fornavbar="true"/> 
</pagenode> 
+1

'' est beaucoup plus succinct –

+0

merci un million! cela fonctionne exactement ce dont j'avais besoin !!! tu es excellent! –

1

XSLT devrait ressembler à ceci:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:template match="pagenode[@fornavbar='true']"> 
    <pagenode> 
     <xsl:copy-of select="@*"/> 
     <xsl:apply-templates/> 
    </pagenode> 
    </xsl:template> 
</xsl:stylesheet> 
+0

Doit être des restes de mon test. – akond

+0

+1 Pour la correction la plus simple. –

3

Ceci est probablement la plus courte et la plus pure solution XSLT:

<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="*[@fornavbar = 'false']"> 
    <xsl:apply-templates/> 
</xsl:template> 
</xsl:stylesheet> 

lorsque cette transformation est appliquée sur le document XML fourni:

<pagenode title="home" url="~/" fornavbar="true"> 
    <pagenode title="admin" url="~/admin" fornavbar="false"> 
     <pagenode title="users" url="~/admin/users" fornavbar="false"/> 
     <pagenode title="events" url="~/admin/events" fornavbar="true"/> 
    </pagenode> 
    <pagenode title="catalog" url="~/catalog" fornavbar="true"/> 
    <pagenode title="contact us" url="~/contactus" fornavbar="false"/> 
</pagenode> 

le résultat recherché, correcte est produite:

<pagenode title="home" url="~/" fornavbar="true"> 
    <pagenode title="events" url="~/admin/events" fornavbar="true"/> 
    <pagenode title="catalog" url="~/catalog" fornavbar="true"/> 
</pagenode> 

Explication:

  1. La règle d'identité (template) copie chaque noeud "tel quel". En utilisant le identity rule et le surcharger est le motif de conception XSLT le plus fondamental.

  2. Il existe un modèle unique qui l'emporte sur la règle d'identité - pour les éléments dont fornavbar attribut est "false". Ici, l'action spécifiée consiste à appliquer-templates sur les enfants de l'élément en cours.

+1

+1 Bonne réponse. Juste pour la logique sémantique et inversée d'une seule solution, j'utiliserais '* [not (self :: pagenode/@ fornavbar = 'true')]' –

+0

@Alejandro: Merci. Que voulez-vous dire? –

+0

Je veux dire que la règle de contournement correspondra à n'importe quel élément ayant un attribut '@ fornavbar' avec une valeur de chaîne '' false'', donc la règle d'identité correspondra à ** tout élément ** n'ayant pas d'attribut' @ fornavbar' avec '' false '' chaîne de caractères, à la place des éléments 'pagenode' ** seulement ** ayant un attribut' @ fornavbar' avec une chaîne de caractères '' true''. –

Questions connexes