Question

I'm new to xslt 2.0. I'm not sure if my question is accurate.

This is the xml file :

<movies>
  <movie>
    <actor>actor 1</actor>
    <actor>actor 2</actor>
    <actor>actor 3</actor>
    <name>movie 1</name>
    <year>1997</year>
  </movie>
  <movie>
    <actor>actor 1</actor>
    <actor>actor 4</actor>
    <actor>actor 5</actor>
    <name>movie 2</name>
    <year>1997</year>
  </movie>
  <movie>
    <actor>actor 1</actor>
    <actor>actor 6</actor>
    <actor>actor 7</actor>
    <name>movie 3</name>
    <year>1995</year>
  </movie>
  <mockumentary>
    <actor>actor 1</actor>
    <actor>actor 8</actor>
    <actor>actor 9</actor>
    <name>movie 4</name>
    <year>2000</year>
  </mockumentary>
  <mockumentary>
    <actor>actor 1</actor>
    <actor>actor 10</actor>
    <actor>actor 11</actor>
    <name>movie 5</name>
    <year>1997</year>
  </mockumentary>
</movies>

Here is what i did so far :

<xsl:template match="/">
  <xsl:variable name="document" select="."/>
  <xsl:for-each select="distinct-values(//actor)">
    <xsl:variable name="actor-value"> <xsl:value-of select="."/> </xsl:variable>
    <xsl:result-document href="{concat($file-name, '.html')}">
    <html>
    <body>
      <!--selects all movie names where the current actor plays-->
      <xsl:apply-templates select="$document//name[../actor=$actor-value]" >
    <xsl:sort select="../year" order="descending" />
    <xsl:sort select="../name" />
  </xsl:apply-templates>
    </body>
    </html>
    </xsl:result-document> 
  </xsl:for-each>
</xsl:template>

<xsl:template match="name">
  <tr><th colspan="3"><xsl:value-of select="../year"/></th></tr>
  <tr>
   <!-- i call here a certain template that lists all actors -->
   <xsl:text> , </xsl:text>
   <xsl:value-of select="../name"/>
  </tr>
</xsl:template>

The resulting html file for actor 1 looks a bit like this :

actor 1.html

What i want to do is to create an html file for each actor. It should contain all the movies in which he played. The movies should be sorted by year and then by name. In other words, if an actor played in 2 movies which have the same year, they should be then sorted by the movie's name. For example, I'm trying to have something like this for "actor 1.html" :

actor 1.html

Noting that movie 1, 2 and 5 should be sorted alphabetically by name.

I'm trying to select these movies : "$document//name[../actor=$actor-value]" by the element year and then make a for-each but i can't seem to know how.

Can anyone please give me an idea how to do it. Thank you!

Was it helpful?

Solution

I finally found it with the help of this answer

I used for-each-group to group the different movies by year.

Here is the new code :

<xsl:template match="/">
  <xsl:variable name="document" select="."/>
  <xsl:for-each select="distinct-values(//actor)">
    <xsl:variable name="actor-value"> <xsl:value-of select="."/> </xsl:variable>
    <xsl:result-document href="{concat($file-name, '.html')}">
    <html>
    <body>
      <p>
      <table>

        <xsl:for-each-group select="$document//name[../actor=$actor-value]" group-by="../year">
    <!--************** SORT BY YEAR **************-->
        <xsl:sort select="../year" data-type="number" order="descending"/>
        <tr><th><xsl:value-of select="../year"/></th></tr>

      <xsl:apply-templates select="current-group()" >
        <!--************** SORT BY TITLE **************-->
        <xsl:sort select="." data-type="text" order="ascending" />
      </xsl:apply-templates>
      </table>
      </p>
      </body>
      </html>
      </xsl:result-document> 
  </xsl:for-each>
</xsl:template>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top