Embed XSL in XML for Display in Web Browser: What am I doing wrong? Embed XSL in XML for Display in Web Browser: What am I doing wrong? xml xml

Embed XSL in XML for Display in Web Browser: What am I doing wrong?


The following code:

<?xml version="1.0" encoding="ISO-8859-1"?><?xml-stylesheet type="text/xsl" href="#stylesheet"?><!DOCTYPE doc [<!ATTLIST xsl:stylesheetid ID #REQUIRED>]><doc> <!--Start XSL--> <xsl:stylesheet id="stylesheet"  version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >  <xsl:template match="xsl:stylesheet" />   <!--Variables-->   <xsl:variable name="a" select="/doc/list/movie/seen[@value ='Yes']" />   <xsl:variable name="b" select="/doc/list/movie/seen" />   <xsl:variable name="c" select="sum(/doc/list/movie/rating/@value)" />   <xsl:variable name="d" select="$c div count($a)" />   <xsl:variable name="e" select="count($a) div count($b)" />   <xsl:variable name="f" select="/doc/list/movie/seen[@value ='No']" />   <xsl:variable name="g" select="/doc/list/movie/seen[@value ='Prior']" />   <xsl:variable name="h" select="count($f) div count($b)" />   <xsl:variable name="j" select="count($g) div count($b)" />   <xsl:variable name="minutes_total" select="sum(/doc/list/movie/length[@value ='y'])" />   <xsl:variable name="minutes" select="$minutes_total mod 60" />   <xsl:variable name="hours" select="floor($minutes_total div 60) mod 24" />   <xsl:variable name="hours2" select="floor($minutes_total div 60)" />   <xsl:variable name="days" select="floor($hours2 div 24)" />   <!--End Variables-->  <xsl:decimal-format name="percent" />  <xsl:decimal-format name="average" decimal-separator="." />  <xsl:template match="/doc">   <html>    <head>     <style>      h2{      font-family: Courier, Courier New, monospace;      font-size: 32px;      text-decoration: underline;      }      body{      font-family: Courier New, monospace;      }      p{      font-size: 16px;      }      table{      font-size: 14px;      }      .title{      text-align:left;      }      .release{      text-align:center;      }      .seen{      text-align:center;      }      .rating{      text-align:right;      }      .length{      text-align:center;      }     </style>    </head>    <body>     <h2>My Movie List</h2>     <p>Movies seen so far: <xsl:value-of select="count($a)" />/<xsl:value-of select="count($b)" /> = <xsl:value-of select="format-number($e, '#%', 'percent')" /><br />     Movies yet to see: <xsl:value-of select="count($f)" />/<xsl:value-of select="count($b)" /> = <xsl:value-of select="format-number($h, '#%', 'percent')" /><br />     Movies seen prior to making list: <xsl:value-of select="count($g)" />/<xsl:value-of select="count($b)" /> = <xsl:value-of select="format-number($j, '#%', 'percent')" /><br />     Total time watched: <xsl:value-of select="format-number($days, '#0')" /> days, <xsl:value-of select="format-number($hours, '#0')" /> hours, <xsl:value-of select="format-number($minutes, '#0')" /> minutes<br />     Average rating:  <xsl:value-of select="format-number($d, '#.000', 'average')" /> stars out of 5</p>     <br />     <table border="1">      <tr>       <th>#</th>       <th>Title</th>       <th>Release Date</th>       <th>Length</th>       <th>Seen</th>       <th>Rating</th>      </tr>      <xsl:for-each select="list/movie">       <xsl:choose>        <xsl:when test='seen = "Yes"'>         <tr style="background-color:#666; color:#fff">          <td> <xsl:number /></td>          <td class="title"><xsl:value-of select="title"/></td>          <td class="release"><xsl:value-of select="release"/></td>          <td class="length"><xsl:value-of select="length" /> minutes</td>          <td class="seen"><xsl:value-of select="seen"/></td>          <td class="rating"><xsl:value-of select="rating"/></td>         </tr>        </xsl:when>        <xsl:when test='seen = "Seen prior to making list"'>         <tr style="background-color:#999; color:#000">          <td> <xsl:number /></td>          <td class="title"><xsl:value-of select="title"/></td>          <td class="release"><xsl:value-of select="release"/></td>          <td class="length"><xsl:value-of select="length"/> minutes</td>          <td class="seen"><xsl:value-of select="seen"/></td>          <td class="rating"><xsl:value-of select="rating"/></td>         </tr>        </xsl:when>        <xsl:otherwise>         <tr style="background-color:#fff;">          <td> <xsl:number /></td>          <td class="title"><xsl:value-of select="title"/></td>          <td class="release"><xsl:value-of select="release"/></td>          <td class="length"><xsl:value-of select="length" /> minutes</td>          <td class="seen"><xsl:value-of select="seen"/></td>          <td class="rating"><xsl:value-of select="rating"/></td>         </tr>        </xsl:otherwise>       </xsl:choose>      </xsl:for-each>     </table>    </body>   </html>  </xsl:template> </xsl:stylesheet> <!--Start XML--> <list>  <movie>   <title>2001: A Space Odyssey</title>   <release>1968</release>   <seen value="No">No</seen>   <rating>N/A</rating>   <length value="n">141</length>  </movie>  <movie>   <title>28 Days Later</title>   <release>2002</release>   <seen value="No">No</seen>   <rating>N/A</rating>   <length value="n">113</length>  </movie>  <movie>   <title>28 Weeks Later</title>   <release>2007</release>   <seen value="No">No</seen>   <rating>N/A</rating>   <length value="n">100</length>  </movie>  <movie>   <title>A Clockwork Orange</title>   <release>1971</release>   <seen value="Yes">Yes</seen>   <rating value="2">&#9734;&#9734;&#9734;&#9733;&#9733;</rating>   <length value="y">136</length>  </movie>  <!--Rest of XML--> </list></doc>

Produces the desired output as shown below when saved as an XML file and opened in the FireFox web browser. Formatting is not displayed here, but will be when you open an XML file containing the above code in FireFox.

My Movie ListMovies seen so far: 1/4 = 25%  Movies yet to see: 3/4 = 75%  Movies seen prior to making list: 0/4 = 0%  Total time watched: 0 days, 2 hours, 16 minutes  Average rating: 2.000 stars out of 5  # Title         Release Date    Length      Seen    Rating  1 2001: A Space Odyssey 1968    141 minutes No      N/A  2 28 Days Later         2002    113 minutes No      N/A  3 28 Weeks Later        2007    100 minutes No      N/A  4 A Clockwork Orange    1971    136 minutes Yes     ☆☆☆★★

Note 1: The problem was the change of element nesting level caused by embedding the XML <list> within the <doc> element when you put the XML and XSL into the single file format. The solution adds /doc before /list in all of your XPath expressions in order to select the desired elements which are now nested one level deeper as descendants of <doc> and <list> instead of just descendants of <list> (like they were when the two files were separate).

Note 2: xml-stylesheet type was also changed to "text/xsl" as a step towards compatibility with IE 8. With the "text/xml" type, IE 8 just displays the document tree (including XSL) as XML, while with "text/xsl" it attempts--albeit rather unsuccessfully--to apply the transformation. More work would be required to make this display correctly in IE 8. Note that either type value works fine in FireFox 7. No other browsers were tested.