web-dev-qa-db-ja.com

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要素に含まれる子要素(名前)が1つだけの場合は、プレーンテキストとして表示する必要があります。

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>

したがって、この場合、Bobはハイパーリンクとして表示され、Mikeはプレーンテキストとして表示されます。ただし、私のページにはボブとマイクの両方がプレーンテキストとして表示されます。

11
Alex

最初のxsl:whenテストはここでは正しくありません

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

ここではすでにactor要素に配置されているため、これは現在のactor要素の子であるactor要素を探します。そして何も見つけません。

あなたはおそらくこれをしたいだけです

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

または、これを行うことができます

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

つまり、2番目の位置に要素がありますか(実際に複数の要素があることだけを確認したい場合に、すべての要素の数を節約できます)。

または、現在のactor要素にname以外の要素があることを確認したい場合は、

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

余談ですが、xsl:chooseを使用するよりも、テストをテンプレートマッチに入れる方がよい場合があります。

この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プロセッサは最初に、より具体的なテンプレートと一致する必要があることに注意してください。

20
Tim C