2013-04-15 10 views
11

Mam następujący plik XML, który przechowuje filmów i aktorów szczegóły:XSLT - policzyć liczbę elementów podrzędnych za pomocą 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> 

Jeśli element actor zawiera więcej niż jeden elementy podrzędne (w tym przypadku jest to nazwa , wiek i wzrost), a następnie chcę wyświetlić jego nazwę jako hiperłącze.

Jeśli jednak element actor zawiera tylko jeden element potomny (nazwę), powinien być wyświetlany jako zwykły tekst.

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> 

Więc w tym przypadku Bob powinien być wyświetlany jako hiperłącze, a Mike powinien być wyświetlany jako zwykły tekst. Jednak moja strona wyświetla zarówno Boba, jak i Mike'a jako zwykły tekst.

Odpowiedz

20

Twój pierwszy xsl: when test jest nieprawidłowy tutaj

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

Jesteś już umieszczony na aktora elementem tutaj, więc będzie to szuka aktora elementu, który jest dzieckiem bieżący element actor i nie znajdujący nic.

Prawdopodobnie po prostu chcesz zrobić

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

Alternatywnie, można to zrobić

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

znaczy, czy jest to element w drugim miejscu (który oszczędza licząc wszystkie elementy, gdy tylko naprawdę chcesz sprawdzić, czy jest więcej niż jeden),

A może chcesz sprawdzić obecny element actor element h jako element inny niż nazwa?

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

Tak na marginesie, to może być lepiej umieścić test w szablonie meczu, zamiast używać xsl: choose.

Try This 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> 

Zauważ, że procesor XSLT powinien dopasować bardziej konkretnego szablonu pierwszy w tym przypadku.

Powiązane problemy