2010-08-04 7 views
3

J'ai créé une feuille de style XSLT qui recherche un noeud et le supprime. Cela fonctionne très bien. Je veux maintenant vérifier pour voir si un certain noeud existe et puis supprimer ce noeud s'il est là.Comment utiliser une instruction XSLT if correctement?

Je tenté d'ajouter une instruction if et c'est si je couru dans l'erreur suivante:

compilation error: file dt.xls line 10 element template
element template only allowed as child of stylesheet

Je pense que je comprends l'erreur, mais ne savez pas comment contourner.

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

    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

    <xsl:template match="Ad"> 
    <xsl:template match="node()|@*"> 

     <xsl:if test="name-ad-size"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
     </xsl:if> 

    </xsl:template> 
    </xsl:template> 


    <xsl:template match="phy-ad-width"/> 
    <xsl:strip-space elements="*"/> 
    <xsl:preserve-space elements="codeListing sampleOutput"/> 
    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 
+0

je fixe la mise en forme, mais votre XSL est invalide parce que vous ne pouvez pas mettre un '

+0

@Jim: aha, j'ai seulement vu le 'xsl: if', donc j'ai deviné le reste du problème. Le reste était parti parce qu'il n'était pas dans un bloc de code. Ah, quoi qu'il en soit, la réponse devrait rester à peu près la même ;-) – Abel

Répondre

5

Le problème, en général, lorsque les gens XSLT tentative est qu'ils pensent qu'il est une langue que tout autre, comme C#, Java, PHP. Toutes ces langues sont utilisées pour dire à l'ordinateur quoi faire. Mais avec XSLT c'est l'inverse, vous dites au processeur quelle sortie vous attendez en fonction des règles.

Parfois, l'utilisation de xsl:if est bonne. Plus souvent, c'est un signe d'erreur. L'astuce pour supprimer nœuds, éléments ou texte est de créer un modèle correspondant qui ne génère rien. Quelque chose comme ceci:

<!-- starting point --> 
<xsl:template match="/"> 
    <xsl:apply-templates select="root/something" /> 
</xsl:template> 

<xsl:template match="name-ad-size"> 
    <!-- don't do anything, continue processing the rest of the document --> 
    <xsl:apply-templates select="node() | @*" /> 
</xsl:template> 

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

Pourquoi cela fonctionne-t-il? Simplement, parce que le processeur passe par chaque élément et noeud et regarde d'abord le meilleur modèle correspondant. La meilleure correspondance pour un noeud <name-ad-size> est la correspondance qui ne génère aucun résultat, ce qui permet de le supprimer efficacement. Les autres nœuds ne correspondent pas et se retrouvent ainsi dans le modèle "catch all".

Remarque 1: l'erreur que vous recevez est probable parce que vous avez ajouté par erreur <xsl:template> dans un autre élément. Il ne peut être placé sous la racine <xsl:stylesheet> et nulle part ailleurs.

Remarque 2: l'ordre des instructions <xsl:template> est sans importance. Le processeur utilisera chacun d'entre eux pour trouver la meilleure correspondance, peu importe où ils sont placés (tant qu'ils sont directement sous la racine).


EDIT: Quelqu'un a récupéré votre code comme par magie. Voici l'histoire ci-dessus appliquée à votre feuille de style complet:

<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:preserve-space elements="codeListing sampleOutput"/> 

    <!-- NOTE: it is better to have a starting point explicitly --> 
    <xsl:template match="/"> 
    <xsl:apply-templates select="root/something" /> 
    </xsl:template> 

    <!-- I assume now that you meant to delete the <Ad> elements --> 
    <xsl:template match="Ad"> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:template> 

    <!-- NOTE: here you were already deleting <phy-ad-width> and everything underneath it --> 
    <xsl:template match="phy-ad-width"/> 

    <!-- NOTE: copies everything that has no matching rule elsewhere --> 
    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 
+0

La clé de l'apprentissage de XSL est que ce n'est pas un langage de programmation impératif. Le processeur XSL n'utilise pas la feuille de style pour piloter le processeur; c'est plutôt le document XML d'entrée (celui que vous traitez, pas la feuille de style) qui contrôle le processus. Au fur et à mesure que chaque étiquette est lue, le processeur décide quoi faire en cherchant dans le XSL le meilleur modèle correspondant. C'est un peu trop simplifié, mais apprendre à penser au document en contrôle, pas à la feuille de style, est le saut intuitif requis. –

+0

@Jim: Je pense que c'est ce que j'essayais de dire. Je connais cette pensée renversée et c'est tout à fait correct, mais j'ai remarqué que les élèves ont du mal à penser que le XML (ou autre entrée) mène. C'est pourquoi j'utilise une comparaison avec des "règles". Quand je travaille avec XSLT, j'écris des règles, quand j'écris des règles, je demande * "si le processeur rencontre un nœud dans le XML d'entrée correspondant à ma règle, que devrions-nous produire?" *. – Abel

+0

wow merci je vois ce que vous dites et votre droite je suis un programmeur C# et je regardais comme ça. Cependant, avant de supprimer le je veux vérifier si le nœud "nom-taille-annonce" existe.la raison pour laquelle j'ai besoin de cette vérification est parfois j'ai besoin de la phy-ad-largeur et parfois je ne sais pas ma clé est le "nom-taille de l'annonce" si cela existe alors je veux supprimer le phy-ad-largeur c'est pourquoi je pensé un si statment pourrait être en ordre ici. merci encore pour cette belle réponse. – Mike