XSLT - подсчет количества дочерних элементов с помощью XPath

У меня есть следующий файл XML, в котором хранятся сведения о фильмах и актерах:

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

Если элемент actor содержит более одного дочернего элемента (в этом случае это имя, возраст и высота), то я хочу отобразить его имя как гиперссылку.

Если, однако, элемент actor содержит только один дочерний элемент (имя), то он должен отображаться как обычный текст.

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>

Итак, в этом случае Боб должен отображаться как гиперссылка, а Майк должен отображаться как обычный текст. Однако на моей странице отображаются оба Боб и Майк в виде обычного текста.

Ответ 1

Ваш первый тест xsl: when здесь неверен

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

Вы уже позиционированы здесь на элементе актер, поэтому он будет искать элемент актер, который является дочерним элементом текущего актера, и ничего не обнаружил.

Вероятно, вы просто хотите это сделать

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

В качестве альтернативы вы можете сделать это

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

i.e, есть ли элемент во второй позиции (который сохраняет подсчет всех элементов, когда вы действительно хотите проверить, что их более одного),

Или, возможно, вы хотите проверить, что текущий элемент актер имеет элемент, отличный от name?

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

В стороне, возможно, лучше поставить тест в соответствие шаблону, а не использовать xsl: выберите.

Попробуйте этот 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>

Обратите внимание, что XSLT-процессор должен сначала соответствовать более конкретному шаблону в этом экземпляре.