2013-04-15 14 views
11

Ho il seguente file XML che contiene i film e gli attori dettagli:XSLT - contare il numero di elementi figlio utilizzando XPath

<database 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="movies.xsd"> 

<movies> 
    <movie movieID="1"> 
     <title>Movie 1</title> 
     <actors> 
      <actor actorID="1"> 
       <name>Bob</name> 
       <age>32</age> 
       <height>182 cm</height> 
      </actor> 
      <actor actorID="2"> 
       <name>Mike</name> 
      </actor> 
     </actors> 
    </movie> 
</movies> 

</database> 

Se l'elemento actor contiene più di un elementi figlio (in questo caso il suo nome , età e altezza) quindi voglio visualizzare il suo nome come collegamento ipertestuale.

Se, tuttavia, l'elemento actor contiene solo un elemento figlio (nome), deve essere visualizzato come testo normale.

XSLT:

<xsl:template match="/"> 
    <div> 
     <xsl:apply-templates select="database/movies/movie"/> 
    </div> 
    </xsl:template> 

    <xsl:template match="movie"> 
    <xsl:value-of select="concat('Title: ', title)"/> 
    <br /> 
    <xsl:text>Actors: </xsl:text> 
    <xsl:apply-templates select="actors/actor" /> 
    <br /> 
    </xsl:template>  

<xsl:template match="actor"> 
    <xsl:choose> 
     <xsl:when test="actor[count(*) &gt; 1]/name"> 
      <a href="actor_details.php?actorID={@actorID}"> 
       <xsl:value-of select="name"/> 
      </a> 
      <br/> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="name"/> 
      <br/> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

Quindi in questo caso Bob dovrebbe essere visualizzato come collegamento ipertestuale, e Mike dovrebbe essere visualizzato come testo normale. Tuttavia, la mia pagina visualizza sia Bob e Mike come testo normale.

risposta

20

Il tuo primo xsl: quando test è errato qui

<xsl:when test="actor[count(*) &gt; 1]/name"> 

Sei già posizionato su un attore elemento qui, quindi questo sarà alla ricerca di un elemento attore che è un figlio di l'attuale elemento attore e non trovando nulla.

Probabilmente vuole solo fare questo

<xsl:when test="count(*) &gt; 1"> 

In alternativa, si potrebbe fare questo

<xsl:when test="*[2]"> 

cioè, c'è un elemento in seconda posizione (che salva contando tutti gli elementi, quando si voglio solo controllare che ce ne siano più di uno),

O forse vuoi controllare l'attuale attore elemento h come elemento diverso da nome?

<xsl:when test="*[not(self::name)]"> 

Per inciso, potrebbe essere meglio per mettere alla prova in un match modello, piuttosto che utilizzare un xsl: choose.

Prova questa XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" encoding="utf-8" omit-xml-declaration="no"/> 

    <xsl:template match="/"> 
     <div> 
     <xsl:apply-templates select="database/movies/movie"/> 
     </div> 
    </xsl:template> 

    <xsl:template match="movie"> 
     <xsl:value-of select="concat('Title: ', title)"/> 
     <br/> 
     <xsl:text>Actors: </xsl:text> 
     <xsl:apply-templates select="actors/actor"/> 
     <br/> 
    </xsl:template> 

    <xsl:template match="actor"> 
     <xsl:value-of select="name"/> 
     <br/> 
    </xsl:template> 

    <xsl:template match="actor[*[2]]"> 
     <a href="actor_details.php?actorID={@actorID}"> 
     <xsl:value-of select="name"/> 
     </a> 
     <br/> 
    </xsl:template> 
</xsl:stylesheet> 

Si noti che il processore XSLT deve corrispondere al modello più specifica prima in questo caso.

Problemi correlati