2013-08-29 4 views
2

j'ai un fragment XML tel que ci-dessousxsl références croisées comparant un nœud avec un autre

<xml> 
<person> 
    <name>bob</name> 
    <holidays> 
     <visit>GB</visit> 
     <visit>FR</visit> 
    </holidays> 
</person> 
<person> 
    <name>joe</name> 
    <holidays> 
     <visit>DE</visit> 
     <visit>FR</visit> 
    </holidays> 
</person> 


<countrylist> 
    <country>GB</country> 
    <country>FR</country> 
    <country>DE</country> 
    <country>US</country> 
</countrylist> 
</xml> 

J'aimerais à la liste tous les pays de la countrylist par oui ou non selon que cette personne a visité le pays ou pas. Ainsi, une sortie pour le code XML ci-dessus comme

Bob 
    GB Yes 
    FR Yes 
    DE No 
    US No 

Joe 
    GB No 
    FR Yes 
    DE Yes 
    US No 

Voici ce que je l'ai essayé jusqu'à présent:

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


<xsl:template match="person"> 
<xsl:value-of select="name"></xsl:value-of> 
    <xsl:apply-templates select="holidays"></xsl:apply-templates> 
</xsl:template> 

<xsl:template match="holidays"> 
      <xsl:variable name="v" select="holidays"></xsl:variable> 
    <xsl:for-each select="/xml/countrylist/country"> 
     <xsl:variable name="vcountry" select="."></xsl:variable> 
     <xsl:if test="$v/holidays[$vcountry]">  
     <xsl:value-of select="$vcountry"></xsl:value-of><xsl:value-of select="'*'"/> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:template> 
</xsl:stylesheet> 

modifier: Je finalement réussi en utilisant le ci-dessous; Y a-t-il un moyen plus facile?

<xsl:template match="xml"> 
    <xsl:apply-templates select="person"> 
    </xsl:apply-templates> 
</xsl:template> 
<xsl:template match="person"> 
    <xsl:variable name="hols" select="holidays"/> 
    <xsl:value-of select="name"/> 
    <xsl:for-each select="/xml/countrylist/country"> 
     <xsl:variable name="vcountry" select="."/> 
     <xsl:if test="$hols[visit=$vcountry]"> 
      <xsl:value-of select="$vcountry"/> 
      <xsl:value-of select="'*'"/> 
     </xsl:if> 
    </xsl:for-each> 
</xsl:template> 

Répondre

1

Si vous souhaitez afficher uniquement les pays que chaque personne visitée (et ne pas afficher aussi un « non » pour ceux qu'ils ne l'ont pas visite) alors vous n'avez pas besoin de faire participer le countrylist à tous

<xsl:template match="person"> 
    <xsl:value-of select="name"/> 
    <xsl:for-each select="holidays/visit"> 
     <xsl:value-of select="." /> 
     <xsl:text> *</xsl:text> 
    </xsl:for-each> 
</xsl:template> 

Si vous ne voulez que les entrées « non », votre approche est très bien, mais vous pouvez simplifier un peu:

<xsl:template match="person"> 
    <xsl:variable name="visits" select="holidays/visit"/> 
    <xsl:value-of select="name"/> 
    <xsl:text> - </xsl:text> 
    <xsl:for-each select="/xml/countrylist/country"> 
     <xsl:value-of select="." /> 
     <xsl:choose> 
      <xsl:when test=". = $visits"> 
       <xsl:text>: Yes </xsl:text> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:text>: No </xsl:text> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:for-each> 
</xsl:template> 

en profitant de le fait qu'une comparaison égale entre un noeud et un ensemble de noeuds est vrai si le noeud à gauche (le country dans ce cas) a la même valeur que aucun des noeuds sur la droite (les éléments visit de la personne actuelle).

+0

excellent ... Merci Ian. C'est un bon conseil! – dmckinney

+0

@dmckinney même étend les comparaisons lorsque vous disposez d'un ensemble de noeuds sur les deux côtés - la comparaison réussit si un nœud de l'ensemble de la main gauche correspond à un nœud de celui de la main droite. C'est pourquoi «x! = Y» et «not (x = y)» peuvent donner des résultats différents - le premier signifie «il y a au moins une paire de x et y qui ne correspondent pas» alors que le second signifie «il y a _no_ paire de x et y que _does_ correspond ". –

Questions connexes