Xsl:apply-templates select issues, Need to specify what year I am pulling

Viewed 39

I am trying to pull movies less than than a certain year and greater than a certain year. Im having issues with my output. This is my XSLT code

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">

    <xsl:output method="html" indent="yes"/>
    <!-- defines the format of the style sheet (html) -->
    <xsl:template match="/">
        <!-- the match attribute is used to connect the template with the xml element match = "/" means match the whole document. -->
        <html>
            <head>
                <title>Movie Listing</title>
                <h1>My Favorite Movies From Before 2005</h1>
                <style type="text/css">
                        table, tr, td, th{background-color:"powderblue"; border: 3px solid black; padding: 5px; border-spacing: 3px;) <!-- style for table -->
                </style>
            </head>

            <body>
                <table>
                    <tr>
                        <td>
                            <b>Movie ID</b>
                        </td>
                        <td>
                            <b>Title</b>
                        </td>
                        <td>
                            <b>Director</b>
                        </td>
                        <td>
                            <b>Year</b>
                        </td>
                        <td>
                            <b>Genres</b>
                        </td>

                        <xsl:apply-templates select ="movies/movie[year&lt;2005]"></xsl:apply-templates>
                        
                        
                        <tr>
                            <td colspan ="3">
                                <b>Number of Movies</b>
                            </td>
                            <td colspan ="2">
                                <xsl:value-of select="count(movies/movie[year&lt;2005])"/>
                            </td>
                        </tr>
                    </tr>
                </table>
            
                <ul>
                    <b>Principal Directors:</b>
                    <xsl:for-each select="movies/movie[year&lt;2005]">
                        <xsl:sort select="pdirector" order="ascending"/>
                        <li>
                            <xsl:value-of select="pdirector"/>
                        </li>
                    </xsl:for-each>
                </ul>
                    

                



                <h1>My Favorite Movies From 2005 Onward</h1>
                <table>
                    <tr>
                        <td>
                            <b>Movie ID</b>
                        </td>
                        <td>
                            <b>Title</b>
                        </td>
                        <td>
                            <b>Director</b>
                        </td>
                        <td>
                            <b>Year</b>
                        </td>
                        <td>
                            <b>Genres</b>
                        </td>

                        <xsl:apply-templates select ="movies/movie[year>=2005]"></xsl:apply-templates>
    
                        <tr>
                            <td colspan ="3">
                                <b>Number of Movies</b>
                            </td>
                            <td colspan ="2">
                                <xsl:value-of select="count(movies/movie[year>=2005])"/>
                            </td>
                        </tr>
                    </tr>
                </table>
                <ul>
                    <b>Principal Directors:</b>
                    <xsl:for-each select="movies/movie[year>=2005]">
                        <xsl:sort select="pdirector" order="ascending"/>
                        <li>
                            <xsl:value-of select="pdirector"/>
                        </li>
                    </xsl:for-each>
                </ul>
            </body>
        </html>
    </xsl:template>
    
    
    
    <xsl:template match="movies">                           <!-- template for data -->
        <xsl:for-each select ="movie">                      <!-- looping through movie -->
            <xsl:sort select="title" order="ascending"/>    <!-- sorting through movie -->
            <tr>
                <td>
                    <xsl:value-of select ="@id"/>
                    <!-- grabbing id-->
                    <br></br>
                </td>
                <td>
                    <!-- grabbing title -->
                    <xsl:element name="a">
                        <xsl:attribute name="href">
                            <xsl:value-of select="url"/>
                        </xsl:attribute>
                        <xsl:value-of select="title"/>
                    </xsl:element>
                    <br></br>
                </td>
                <td>
                    <xsl:value-of select ="pdirector"/>
                    <!-- grabbing pdirector -->
                    <br></br>
                </td>
                <td>
                    <xsl:value-of select ="year"/>
                    <!-- grabing year -->
                    <br></br>
                </td>
                <td>
                    <xsl:for-each select ="genres">
                        <xsl:value-of select="genre"/>, 
                        <xsl:value-of select="genre[2]"/>, 
                        <xsl:value-of select="genre[3]"/>
                        <br></br>
                    </xsl:for-each>
                </td>
            </tr>
    
    
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

The statements where I apply the actual templates seem to be giving me the issues because when I leave them empty and I just pull everything its formatted correctly.

<xsl:apply-templates></xsl:apply-templates>

When I go ahead and set a condition to pull the movies from, my output goes wrong

Code:

<xsl:apply-templates select="movies/movie[year&lt;2005]"></xsl:apply-templates>

and
  
<xsl:apply-templates select="movies/movie[year>=2005]"></xsl:apply-templates>
2 Answers

A quick (partial) solution would be replacing the XPath expression in your <xsl:apply-templates ...> from

<xsl:apply-templates select="movies/movie[year&lt;2005]"></xsl:apply-templates>

to

<xsl:apply-templates select="movies[movie/year&lt;2005]"></xsl:apply-templates>

(Also apply this change to the second expression making it movies[movie/year>=2005])

With this change, the movies template will match and you'll get a (more) useful output. The output is still not perfect, but you'll get closer to what you want, I guess.

The problem before has been that you selected "movie" elements without a matching template. Now your select "movies" elements that match your template.


EDIT:: A fully improved version of your XSLT-1.0 stylesheet could be the following:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">

    <xsl:output method="html" indent="yes"/>
    <!-- defines the format of the style sheet (html) -->
    
    <xsl:template match="/movies">
        <!-- the match attribute is used to connect the template with the xml element match = "/" means match the whole document. -->
        <html>
            <head>
                <title>Movie Listing</title>
                <style type="text/css">
                        table, tr, td, th{background-color:"powderblue"; border: 3px solid black; padding: 5px; border-spacing: 3px;) <!-- style for table -->
                </style>
            </head>
            <body>
                <h1>My Favorite Movies before 2005</h1>
                <xsl:call-template name="favorites">
                    <xsl:with-param name="listMovies" select="movie[year&lt;2015]" />
                </xsl:call-template>                
                <h1>My Favorite Movies From 2005 Onward</h1>
                <xsl:call-template name="favorites">
                    <xsl:with-param name="listMovies" select="movie[year>=2015]" />
                </xsl:call-template>                
            </body>
        </html>
    </xsl:template>
    
    <xsl:template name="favorites">
        <xsl:param name="listMovies" />
        <table>
            <tr>
                <td>
                    <b>Movie ID</b>
                </td>
                <td>
                    <b>Title</b>
                </td>
                <td>
                    <b>Director</b>
                </td>
                <td>
                    <b>Year</b>
                </td>
                <td>
                    <b>Genres</b>
                </td>
            </tr>
            <xsl:apply-templates select ="$listMovies">
                <xsl:sort select="title" order="ascending" />
            </xsl:apply-templates>
            <tr>
                <td colspan ="3">
                    <b>Number of Movies</b>
                </td>
                <td colspan ="2">
                    <xsl:value-of select="count($listMovies)"/>
                </td>
            </tr>
        </table>
        <ul>
            <b>Principal Directors:</b>
            <xsl:for-each select="$listMovies">
                <xsl:sort select="pdirector" order="ascending"/>
                <li>
                    <xsl:value-of select="pdirector"/>
                </li>
            </xsl:for-each>
        </ul>
    </xsl:template>
    
    <xsl:template match="movie">                           <!-- template for data -->
        <tr>
            <td>
                <xsl:value-of select ="@id"/>
                <!-- grabbing id-->
                <br></br>
            </td>
            <td>
                <!-- grabbing title -->
                <xsl:element name="a">
                    <xsl:attribute name="href">
                        <xsl:value-of select="url"/>
                    </xsl:attribute>
                    <xsl:value-of select="title"/>
                </xsl:element>
                <br></br>
            </td>
            <td>
                <xsl:value-of select ="pdirector"/>
                <!-- grabbing pdirector -->
                <br></br>
            </td>
            <td>
                <xsl:value-of select ="year"/>
                <!-- grabing year -->
                <br></br>
            </td>
            <td>
                <xsl:for-each select ="genres">
                    <xsl:value-of select="genre"/>, 
                    <xsl:value-of select="genre[2]"/>, 
                    <xsl:value-of select="genre[3]"/>
                    <br></br>
                </xsl:for-each>
            </td>
        </tr>
    </xsl:template>
</xsl:stylesheet>

The solution is very simple. Instead of:

<xsl:apply-templates select ="movies/movie[year&lt;2005]"></xsl:apply-templates>

do:

<xsl:apply-templates select="movies/movie[year&lt;2005]">
    <xsl:sort select="title" order="ascending"/> 
</xsl:apply-templates>

and then change:

<xsl:template match="movies">                           <!-- template for data -->
    <xsl:for-each select ="movie">                      <!-- looping through movie -->
        <xsl:sort select="title" order="ascending"/>    <!-- sorting through movie -->
        <tr>
            <!-- omitted for brevity -->
        </tr>
    </xsl:for-each>
</xsl:template>

to:

<xsl:template match="movie">
    <tr>
        <!-- omitted for brevity -->
    </tr>
</xsl:template>

Untested, because no input XML was provided.

Related