2009-11-24 7 views
17

est ici les données de l'échantillon:Expression XPath pour sélectionner tous les nœuds enfants XML à l'exception d'une liste spécifique?

<catalog> 
    <cd> 
     <title>Empire Burlesque</title> 
     <artist>Bob Dylan</artist> 
     <country>USA</country> 
       <customField1>Whatever</customField1> 
       <customField2>Whatever</customField2> 
       <customField3>Whatever</customField3> 
     <company>Columbia</company> 
     <price>10.90</price> 
     <year>1985</year> 
    </cd> 
    <cd> 
     <title>Hide your heart</title> 
     <artist>Bonnie Tyler</artist> 
     <country>UK</country> 
       <customField1>Whatever</customField1> 
       <customField2>Whatever</customField2> 
     <company>CBS Records</company> 
     <price>9.90</price> 
     <year>1988</year> 
    </cd> 
    <cd> 
     <title>Greatest Hits</title> 
     <artist>Dolly Parton</artist> 
     <country>USA</country> 
       <customField1>Whatever</customField1> 
     <company>RCA</company> 
     <price>9.90</price> 
     <year>1982</year> 
    </cd> 
</catalog> 

que je veux sélectionner tout sauf les éléments de prix et l'année. Je m'attendrais à écrire quelque chose comme le ci-dessous, qui ne fonctionne évidemment pas.

<?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="/"> 
    <html> 
    <body> 
    <xsl:for-each select="//cd/* except (//cd/price|//cd/year)"> 
    Current node: <xsl:value-of select="current()"/> 
    <br /> 
    </xsl:for-each> 
    </body> 
    </html> 
</xsl:template> 
</xsl:stylesheet> 

Veuillez m'aider à trouver un moyen d'exclure certains éléments enfants.

Répondre

37
<xsl:for-each select="//cd/*[not(self::price or self::year)]"> 

Mais en réalité c'est mauvais et inutilement compliqué. Mieux:

<xsl:template match="catalog"> 
    <html> 
    <body> 
     <xsl:apply-templates select="cd/*" /> 
    </body> 
    </html> 
</xsl:template> 

<!-- this is an empty template to mute any unwanted elements --> 
<xsl:template match="cd/price | cd/year" /> 

<!-- this is to output wanted elements --> 
<xsl:template match="cd/*"> 
    <xsl:text>Current node: </xsl:text> 
    <xsl:value-of select="."/> 
    <br /> 
</xsl:template> 

Évitez <xsl:for-each>. Presque tout le temps, c'est le mauvais outil et devrait être remplacé par <xsl:apply-templates> et <xsl:template>.

Ce qui précède fonctionne à cause de la spécificité d'expression de correspondance. match="cd/price | cd/year" est plus spécifique que match="cd/*", donc c'est le modèle préféré pour les éléments cd/price ou cd/year. N'essayez pas d'exclure des nœuds, laissez-les venir et manipulez-les en les jetant.

+2

Merci pour l'explication. –

9

Je commence à expérimenter avec quelque chose comme

"//cd/*[(name() != 'price') and (name() != 'year')]" 

Ou vous venez de correspondance de modèle récursif normale avec <xsl:apply-templates/>, et ensuite des modèles vides pour <price/> et <year/> éléments:

<xsl:template match="price"/> 
<xsl:template match="year"/> 
Questions connexes