Embed XSL in XML for display in a web browser: what am I doing wrong?

So, I tried to investigate this, and I'm almost completely leaving. I found a way to embed XSL in XML on dpawson.co.uk , but I cannot figure out what I'm doing wrong. I searched the Internet, trying to find solutions and explanations, but no one seemed to get an answer.

I am trying to create a single file that is server independent, so I can send one file to my colleagues in the hope that they will be able to view the file by opening it in their web browser.

Here is my code:

<?xml version="1.0" encoding="ISO-8859-1"?> <!--Start XSL--> <?xml-stylesheet type="text/xml" href="#stylesheet"?> <!DOCTYPE doc [ <!ATTLIST xsl:stylesheet id ID #REQUIRED> ]> <doc> <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="list/movie/seen[@value ='Yes']" /> <xsl:variable name="b" select="list/movie/seen" /> <xsl:variable name="c" select="sum(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="list/movie/seen[@value ='No']" /> <xsl:variable name="g" select="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(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)" /> <xsl:decimal-format name="percent" /> <xsl:decimal-format name="average" decimal-separator="." /> <!--End Variables--> <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> 

This is a list of films that contain as much as I have seen so far, how many I have not seen, how many I saw before I compiled the list, the total amount of time I added to watching movies and the average rating for watching a movie.

The problem is that all variables are displayed with a zero value, which leads to division by zeros, which also give a NaN value for some output.

Anything you can offer will be greatly appreciated!

+6
source share
1 answer

The following code:

 <?xml version="1.0" encoding="ISO-8859-1"?> <?xml-stylesheet type="text/xsl" href="#stylesheet"?> <!DOCTYPE doc [ <!ATTLIST xsl:stylesheet id 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> 

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

 My Movie List Movies 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 to change the level of nesting of elements caused by nesting the XML <list> in the <doc> element when you put XML and XSL in a single file format. The solution adds /doc to /list in all your XPath expressions to select the elements you want, which are now nested one level deeper as descendants of <doc> and <list> instead of just descendants of <list> (for example, they were when two files were separate).

Note 2: the xml-stylesheet type has also been 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, and with "text / xsl "he is trying - albeit rather unsuccessfully - to apply the conversion. For this display to display correctly in IE 8, more work is required. Please note that any type value works fine in FireFox 7. No other browsers have been tested.

+8
source

Source: https://habr.com/ru/post/909777/


All Articles