I am doing XML to HTML conversion and I worked out the xslt and on this, single problem still remains that I could not solve.
<?xml version="1.0" encoding="UTF-8"?>
<o>
<abstract-short type="string"><p>Last month a high court judge ruled that, for the purposes of inheritance tax, all let property is classed the same…</p></abstract-short>
<content type="string"><p>Last month a<em>high court</em> judgr maydeal with weekly (or r queries and requests then it is still classed an investment, not a business.</p><p>An appeal against this<em>decision</em> destourist industry and the role it plays in the wider South West economy.</p></content>
<created type="string">2013-02-21T23:59:00</created>
<creator class="object">
<text type="string">[creatorName]</text>
<uri type="string">[creator]</uri>
</creator>
<identifier type="string">https://www.gazettes.co.uk/content/6</identifier>
<issued type="string">2013-06-31T23:59:00</issued>
<position type="string">related pane first</position>
<relation class="array">
<e type="string">wills-and-probate</e>
</relation>
<rights type="string">[copyrightattributionURI]</rights>
<source class="object">
<text type="string">Western Morning News</text>
<uri type="string">http://www.thisisdevon.co.uk/story-18208063-detail/story.html#axzz2M0VVYB82</uri>
</source>
<subject type="string">news</subject>
<title type="string">Arguing the case for appeal over tax ruling</title>
<weight type="string">0</weight>
</o>
And my xslt code is
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml" exclude-result-prefixes="#all">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="o">
<xsl:text disable-output-escaping="yes"><!DOCTYPE html></xsl:text>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
prefix="dcterms: http://purl.org/dc/terms/ dc: http://purl.org/dc/elements/1.1/ gz: https://www.gazettes.co.uk/metadata">
<xsl:apply-templates select="title"/>
</html>
</xsl:template>
<xsl:template match="o/title">
<head>
<title property="dc:title">
<xsl:attribute name="about">
<xsl:value-of select="./parent::o/child::identifier"/>
</xsl:attribute>
<xsl:apply-templates/>
</title>
<meta name="dcterms.format" content="application/xhtml+xml"/>
<xsl:apply-templates
select="./parent::o/child::subject, ./parent::o/child::identifier, ./parent::o/child::relation, ./parent::o/child::position, ./parent::o/child::weight"
/>
</head>
<xsl:apply-templates select="./parent::o/child::created[#type='string']"/>
</xsl:template>
<!-- # Matching Meta content -->
<xsl:template match="o/created[#type='string']">
<body>
<article>
<header>
<h1 class="title">
<xsl:value-of select="./parent::o/child::title[#type='string']"/>
</h1>
</header>
<dl>
<dt>Created date</dt>
<dd property="dcterms:created">
<xsl:attribute name="content">
<xsl:value-of select="."/>
</xsl:attribute>
<xsl:attribute name="about">
<xsl:value-of select="./parent::o/child::identifier"/>
</xsl:attribute>
<xsl:value-of select="substring-before(., 'T')"/>
</dd>
<xsl:apply-templates select="./parent::o/child::issued, ./parent::o/child::source"/>
</dl>
<xsl:apply-templates
select="./parent::o/child::abstract-short, ./parent::o/child::abstract-long, ./parent::o/child::content"
/>
</article>
</body>
</xsl:template>
<xsl:template match="o/subject">
<meta name="dcterms.subject">
<xsl:attribute name="content">
<xsl:apply-templates/>
</xsl:attribute>
</meta>
</xsl:template>
<xsl:template match="o/identifier">
<meta name="dcterms.identifier">
<xsl:attribute name="content">
<xsl:apply-templates/>
</xsl:attribute>
</meta>
</xsl:template>
<xsl:template match="o/relation/e">
<meta name="dcterms.relation">
<xsl:attribute name="content">
<xsl:apply-templates/>
</xsl:attribute>
<xsl:attribute name="scheme">
<xsl:value-of select="'isPartOf'"/>
</xsl:attribute>
</meta>
</xsl:template>
<xsl:template match="o/position">
<meta name="gz.position">
<xsl:attribute name="content">
<xsl:apply-templates/>
</xsl:attribute>
</meta>
</xsl:template>
<xsl:template match="o/weight">
<meta name="gz.weight">
<xsl:attribute name="content">
<xsl:apply-templates/>
</xsl:attribute>
</meta>
</xsl:template>
<xsl:template match="o/issued">
<dt>Publication date</dt>
<dd property="dcterms:issued">
<xsl:attribute name="content">
<xsl:value-of select="."/>
</xsl:attribute>
<xsl:attribute name="about">
<xsl:value-of select="./parent::o/child::identifier"/>
</xsl:attribute>
<xsl:value-of select="substring-before(., 'T')"/>
</dd>
</xsl:template>
<xsl:template match="o/source">
<dt>Source</dt>
<dd property="dc:source">
<xsl:attribute name="content">
<xsl:value-of select="./uri[#type='string']"/>
</xsl:attribute>
<xsl:attribute name="about">
<xsl:value-of select="./parent::o/child::identifier"/>
</xsl:attribute>
<xsl:value-of select="./text[#type='string']"/>
</dd>
</xsl:template>
<!-- # Matching abstract short and long content -->
<xsl:template match="o/abstract-long">
<section class="abstract-long" property="dcterms:abstract">
<xsl:attribute name="about">
<xsl:value-of select="./parent::o/child::identifier"/>
</xsl:attribute>
<xsl:for-each select="./*">
<xsl:element name="{name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:for-each>
</section>
</xsl:template>
<xsl:template match="o/abstract-short">
<section class="abstract-short" property="dcterms:abstract">
<xsl:attribute name="about">
<xsl:value-of select="./parent::o/child::identifier"/>
</xsl:attribute>
<xsl:for-each select="./*">
<xsl:element name="{name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:for-each>
</section>
</xsl:template>
<!-- # Matching body content -->
<xsl:template match="o/content">
<section class="content">
<xsl:for-each select="./*">
<xsl:element name="{name()}">
<xsl:for-each select="#*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:element>
</xsl:for-each>
</section>
</xsl:template>
<xsl:template match="o/rights"></xsl:template>
<xsl:template match="o/creator"></xsl:template>
</xsl:stylesheet>
But, here, my problem is, I did not get any child elements such as em, a from the template <xsl:template match="o/content". What's mistake I have made on this. please explain.Thanks in advance.
If you just want to copy all the children of <content>...</content> change your <xsl:template match="o/content"> to:
<xsl:template match="o/content">
<section class="content">
<xsl:copy-of select="node()"/>
</section>
</xsl:template>
Related
Note sure how to make one of your online test environments for this issue.
Test XSL script:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" version="4.01"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype-public="//W3C//DTD XHTML 1.0 Transitional//EN"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<xsl:attribute name="lang">
<xsl:value-of select="//Settings//LanguageCode"/>
</xsl:attribute>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<link rel="stylesheet" type="text/css">
<xsl:attribute name="href">
<xsl:value-of select="//Settings/Template/#Style"/>
</xsl:attribute>
</link>
<title>
<!--<xsl:value-of select="//Labels/ReportTitleWorksheets"/>-->
Assignment Slips
</title>
<style type="text/css">
#import url('<xsl:text>2020/</xsl:text><xsl:value-of select="//Settings/Template/#Style"/>');
</style>
</head>
<body>
<xsl:for-each select="AssignmentSlips/Page">
<div class="containerPage">
<xsl:if test="#PageBreakBefore=1">
<br style="page-break-before: always;"/>
</xsl:if>
<xsl:for-each select="StudentSlip">
<div class="containerSlip">
<img alt="s89" width="323px" height="429px">
<xsl:attribute name="src">
<xsl:text>2020\</xsl:text>
<xsl:value-of select="//Settings/Template"/>
</xsl:attribute>
</img>
<div class="fieldName">
<xsl:attribute name="dir">
<xsl:value-of select="//Settings/Direction"/>
</xsl:attribute>
<xsl:value-of select="Student"/>
</div>
<div class="fieldAssisant">
<xsl:attribute name="dir">
<xsl:value-of select="//Settings/Direction"/>
</xsl:attribute>
<xsl:value-of select="Assistant"/>
</div>
<div class="fieldDate">
<xsl:attribute name="dir">
<xsl:value-of select="//Settings/Direction"/>
</xsl:attribute>
<xsl:value-of select="Date"/>
</div>
<div class="fieldCounsel">
<xsl:choose>
<xsl:when test="#ItemPosition='1' and Assistant!=''">
<xsl:text>1st: </xsl:text>
</xsl:when>
<xsl:when test="#ItemPosition='2'">
<xsl:text>2nd: </xsl:text>
</xsl:when>
<xsl:when test="#ItemPosition='3'">
<xsl:text>3rd: </xsl:text>
</xsl:when>
</xsl:choose>
<xsl:attribute name="dir">
<xsl:value-of select="//Settings/Direction"/>
</xsl:attribute>
<xsl:value-of select="StudyPoint"/>
</div>
<xsl:choose>
<xsl:when test="Assignment=1">
<div class="checkBibleReading">✓</div>
</xsl:when>
<xsl:when test="Assignment=2">
<div class="checkInitialCall">✓</div>
<div class="fieldInitialCallIndex">
<xsl:choose>
<xsl:when test="#ItemPosition='1'">
<xsl:text>#1</xsl:text>
</xsl:when>
<xsl:when test="#ItemPosition='2'">
<xsl:text>#2</xsl:text>
</xsl:when>
<xsl:when test="#ItemPosition='3'">
<xsl:text>#3</xsl:text>
</xsl:when>
</xsl:choose>
</div>
</xsl:when>
<xsl:when test="Assignment=3">
<div class="checkFirstReturnVisit">✓</div>
<div class="fieldFirstReturnVisitIndex">
<xsl:choose>
<xsl:when test="#ItemPosition='1'">
<xsl:text>#1</xsl:text>
</xsl:when>
<xsl:when test="#ItemPosition='2'">
<xsl:text>#2</xsl:text>
</xsl:when>
<xsl:when test="#ItemPosition='3'">
<xsl:text>#3</xsl:text>
</xsl:when>
</xsl:choose>
</div>
</xsl:when>
<xsl:when test="Assignment=4">
<div class="checkSecondReturnVisit">✓</div>
<div class="fieldSecondReturnVisitIndex">
<xsl:choose>
<xsl:when test="#ItemPosition='1'">
<xsl:text>#1</xsl:text>
</xsl:when>
<xsl:when test="#ItemPosition='2'">
<xsl:text>#2</xsl:text>
</xsl:when>
<xsl:when test="#ItemPosition='3'">
<xsl:text>#3</xsl:text>
</xsl:when>
</xsl:choose>
</div>
</xsl:when>
<xsl:when test="Assignment=5">
<div class="checkThirdReturnVisit">✓</div>
</xsl:when>
<xsl:when test="Assignment=6">
<div class="checkBibleStudy">✓</div>
</xsl:when>
<xsl:when test="Assignment=7">
<div class="checkTalk">✓</div>
</xsl:when>
<xsl:when test="Assignment=0">
<div class="checkOther">✓</div>
<div class="fieldOther">
<xsl:attribute name="dir">
<xsl:value-of select="//Settings/Direction"/>
</xsl:attribute>
<xsl:value-of select="Other"/>
</div>
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="Location=1">
<div class="checkMainHall">✓</div>
</xsl:when>
<xsl:when test="Location=2">
<div class="checkAuxClass1">✓</div>
</xsl:when>
<xsl:when test="Location=3">
<div class="checkAuxClass2">✓</div>
</xsl:when>
</xsl:choose>
</div>
</xsl:for-each>
</div>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Test XML data:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="AssignmentSlips-2020-v1.xsl"?>
<AssignmentSlips Version="230800">
<Settings>
<LanguageCode>zu</LanguageCode>
<Template Style="s-89-zul.css">s-89-zul.jpg</Template>
<Direction>ltr</Direction>
<ForeignGroupMode>0</ForeignGroupMode>
</Settings>
<Page PageBreakBefore="0">
<StudentSlip ItemPosition="0">
<Student></Student>
<StudyPoint></StudyPoint>
<Material></Material>
<Assignment ItemCount="1">1</Assignment>
<Location>1</Location>
<Date>ULwesine 9 Februwari 2023</Date>
</StudentSlip>
<StudentSlip ItemPosition="1">
<Student></Student>
<StudyPoint></StudyPoint>
<Assignment ItemCount="1">2</Assignment>
<Location>1</Location>
<Date>ULwesine 9 Februwari 2023</Date>
</StudentSlip>
<StudentSlip ItemPosition="2">
<Student></Student>
<StudyPoint></StudyPoint>
<Assignment ItemCount="1">3</Assignment>
<Location>1</Location>
<Date>ULwesine 9 Februwari 2023</Date>
</StudentSlip>
<StudentSlip ItemPosition="3">
<Student></Student>
<StudyPoint></StudyPoint>
<Material></Material>
<Assignment ItemCount="1">6</Assignment>
<Location>1</Location>
<Date>ULwesine 9 Februwari 2023</Date>
</StudentSlip>
</Page>
</AssignmentSlips>
The referenced CSS / JPG files are in a 2020 sub folder:
https://www.dropbox.com/s/vbbqr10gbgmil8s/2020.zip?dl=0
When I open the XML file with Microsoft Edge the display is blank.
When I did manage to view the source it was cropped:
<!DOCTYPE html PUBLIC "//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="zu" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
<link rel="stylesheet" type="text/css" href="s-89-zul.css" />
<title>
Assignment Slips
</title>
<style type="text/css">
#import url('2020/s-89-zul.css');
</style>
</head>
<body>
<div class="containerPage">
<div class="containerSlip">
<img alt="s89" width="323px" height="429px" src="2020\s-89-zul.jpg" />
<div class="fieldName" dir="ltr">
</div>
<div class="fieldAssisant" dir="ltr">
</div>
<div class="fieldDate" dir="ltr">ULwesine 9 Februwari 2023</div>
<div class="fieldCounsel" dir="ltr">
</div>
<div class="checkBibleReading">✓</div>
<div class="checkMainHall">✓</div>
</div>
<div class="containerSlip">
<img alt="s89" width="323px" height="429px" src="2020\s-89-zul.jpg" />
<div class="fieldName" dir="ltr">
</div>
<div class="fieldAssisant" dir="ltr">
</div>
<div class="fieldDate" dir="ltr">ULwesine 9 Februwari 2023</div>
<div class="fieldCounsel" dir="ltr">
</div>
<div class="checkInitialCall">✓</div>
<div class="fieldInitialCallIndex">#1</div>
<div class="checkMainHall">✓</div>
</div>
<div class="containerSlip">
<img alt="s89" width="323px" height="429px" src="2020\s-89-zul.jpg" />
<div class="fieldName" dir="ltr">
</div>
<div class="fieldAssisant" dir="ltr">
</div>
<div class="fieldDate" dir="ltr">ULwesine 9 Februwari 2023</div>
<div class="fieldCounsel">2nd:
What have I done wrong here?
Your first problem is that you are testing this code in an environment that gives very poor diagnostics. Ideally, test your code in an XSLT development tool such as Oxygen. If you can only test it in the browser, use a browser like Chrome with a decent developer's console.
When I run it in XSLTfiddle (https://www.xsltfiddle.liberty-development.net) I get a clear error message:
Error executing XSLT at line 70 : An attribute node (dir) cannot be
created after a child of the containing element. Most recent element
start tag was output at line 58 of module
If you look at the surrounding code:
<div class="fieldCounsel">
<xsl:choose>
<xsl:when test="#ItemPosition='1' and Assistant!=''">
<xsl:text>1st: </xsl:text>
</xsl:when>
<xsl:when test="#ItemPosition='2'">
<xsl:text>2nd: </xsl:text>
</xsl:when>
<xsl:when test="#ItemPosition='3'">
<xsl:text>3rd: </xsl:text>
</xsl:when>
</xsl:choose>
<xsl:attribute name="dir">
<xsl:value-of select="//Settings/Direction"/>
</xsl:attribute>
<xsl:value-of select="StudyPoint"/>
</div>
It's perfectly clear that the xsl:choose is creating a text node, and you then follow this with an instruction that creates an attribute. You need to create the attributes of an element before you create the children.
I am trying to brush up on my XML skills and was taking a course on it. There is one where I am tasked to create a XML transform from an XML instance that contains APA and MLA citations.
This is where I am stuck, I have set up my XPaths but, not sure if they are set up properly. Also looking at the transform provided to me I am not sure where to put each value-of statement to get the correct results.
Any help and explanation would be greatly appreciated!
My Code:
<?xml version="1.0" encoding="UTF-8"?>
<bibliography xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="bibliography.xsd" styleToOutput="APA and MLA">
<article>
<authors>
<author>
<lastName>Devine</lastName>
<otherNames>Patricia G.</otherNames>
<otherInitials>P.G.</otherInitials>
</author>
<author>
<lastName>Sherman</lastName>
<otherNames>Steven J.</otherNames>
<otherInitials>S.J.</otherInitials>
</author>
</authors>
<title>Intuitive Versus Rational Judgment and the Role of Stereotyping in the Human Condition: Kirk or Spock?</title>
<parent type="Periodical">
<title>Psychological Inquiry</title>
<volume>3</volume>
<number>2</number>
<date>1992</date>
<pages>153-159</pages>
</parent>
</article>
</bibliography>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" method="xml" omit-xml-declaration="yes"/>
<xsl:template match="/">
<html>
<head>
<title>Bibliography Formatter</title>
</head>
<body>
<h1>Output in <xsl:value-of select="bibliography/#styleToOutput"/> Style</h1>
<xsl:for-each select="//article">
<xsl:if test="contains(/bibliography/#styleToOutput, 'APA')">
<h2>APA Style</h2>
<p>
<xsl:for-each select="/parent">
<xsl:if test="position()!=last()">, & </xsl:if>
</xsl:for-each> (). <xsl:value-of select="/title"/><xsl:text> </xsl:text>
<i></i>, </p>
</xsl:if>
<xsl:if test="contains(/bibliography/#styleToOutput, 'MLA')">
<h2>MLA Style</h2>
<p>
<xsl:for-each select="/authors/author">
<xsl:choose>
<xsl:when test="position()=1">
</xsl:when>
<xsl:otherwise>, and <xsl:text> </xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each></p>
</xsl:if>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Expected output
The code below doesn't do pixel-perfect render, but you should get the idea and complete it the way you need.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" method="xml" omit-xml-declaration="yes"/>
<xsl:template match="/">
<html>
<head>
<title>Bibliography Formatter</title>
</head>
<body>
<h1>Output in <xsl:value-of select="bibliography/#styleToOutput"/> Style</h1>
<xsl:for-each select="//article">
<xsl:if test="contains(/bibliography/#styleToOutput, 'APA')">
<h2>APA Style</h2>
<p>
<xsl:call-template name="drawAuthors"/>
<xsl:for-each select="parent">
<xsl:if test="position()!=last()">, & </xsl:if>
</xsl:for-each> (). <xsl:value-of select="title"/><xsl:text> </xsl:text>
<i></i>, </p>
</xsl:if>
<xsl:if test="contains(/bibliography/#styleToOutput, 'MLA')">
<h2>MLA Style</h2>
<p>
<xsl:call-template name="drawAuthors"/>
<xsl:value-of select="title"/>
</p>
</xsl:if>
</xsl:for-each>
</body>
</html>
</xsl:template>
<xsl:template name="drawAuthors">
<xsl:for-each select="authors/author">
<xsl:choose>
<xsl:when test="position()=1">
</xsl:when>
<xsl:otherwise>, and <xsl:text> </xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:value-of select="lastName"/>
<xsl:value-of select="otherInitials"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
I would use mode's like this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="UTF-8" method="html" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:variable name="styleOutput" select="/bibliography/#styleToOutput"/>
<xsl:variable name="useModeMLA" select="contains(/bibliography/#styleToOutput, 'MLA')"/>
<xsl:template match="/">
<html>
<head>
<title>Bibliography Formatter</title>
</head>
<body>
<h1>Output in <xsl:value-of select="$styleOutput"/> Style</h1>
<xsl:if test="contains($styleOutput, 'APA')">
<h2>APA Style</h2>
<xsl:apply-templates mode="APA"/>
</xsl:if>
<xsl:if test="contains($styleOutput, 'MLA')">
<h2>MLA Style</h2>
<xsl:apply-templates mode="MLA"/>
</xsl:if>
</body>
</html>
</xsl:template>
<xsl:template match="article" mode="APA">
<p>
<xsl:apply-templates select="authors/author" mode="APA"/>
<xsl:text>. </xsl:text>
<xsl:apply-templates select="parent/date" mode="APA"/>
<xsl:value-of select="title"/>
<xsl:apply-templates select="parent" mode="APA"/>
<xsl:text>.</xsl:text>
</p>
</xsl:template>
<xsl:template match="author" mode="APA">
<xsl:if test=" position()=last()">
<xsl:text>, & </xsl:text>
</xsl:if>
<xsl:value-of select="concat(lastName,', ',otherInitials)"/>
</xsl:template>
<xsl:template match="date" mode="APA">
<xsl:value-of select="concat('(',.,'). ')"/>
</xsl:template>
<xsl:template match="parent" mode="APA">
<i>
<xsl:value-of select="title"/>
</i>
<xsl:value-of select="concat(' , ',volume,' (',number,'), ',pages)"/>
</xsl:template>
<xsl:template match="article" mode="MLA">
<p>
<xsl:apply-templates select="authors/author" mode="MLA"/>
<xsl:text>. </xsl:text>
<xsl:value-of select="title"/>
<xsl:apply-templates select="parent" mode="MLA"/>
<xsl:text>.</xsl:text>
</p>
</xsl:template>
<xsl:template match="author" mode="MLA">
<xsl:if test=" position()=last()">
<xsl:text>, and </xsl:text>
</xsl:if>
<xsl:value-of select="concat(lastName,', ',otherNames)"/>
</xsl:template>
<xsl:variable name="quote">"</xsl:variable>
<xsl:template match="parent" mode="MLA">
<i>
<xsl:value-of select="concat($quote,title,$quote)"/>
</i>
<xsl:value-of select="concat(' , ',volume,'.',number,' (',date,'): ',pages)"/>
</xsl:template>
</xsl:stylesheet>
I am fairly new to xml and I'm having a weird problem with templates. For empty data nodes, instead of displaying a blank space where the data should be, I want to display a message like 'None Found' or 'No Data' on an html page. I have done both an xsl:choose statement and 2 xsl:if statements with no success. I already know this particular node is empty, I just want to show a message instead of a blank space. The Otherwise or False statements just don't seem to run at all. Please help!! What am I doing wrong here?
The XML Code
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<findings>
<ssns/>
<dobs>
<dob>
<data>082967</data>
</dob>
</dobs>
<dobs>
<dob>
<data>020568</data>
</dob>
</dobs>
<names>
<name>
<full>Homer J Simpson</full>
<first>Homer</first>
<last>Simpson</last>
<middle>J</middle>
</name>
</names>
<names>
<name>
<full>Marge H Simpson</full>
<first>Marge</first>
<last>Simpson</last>
<middle>H</middle>
</name>
</names>
</findings>
</Root>
The XSL Code
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<hmtl>
<head>
<title>Person Results</title>
</head>
<div style="font-weight:bold">Alias(es):</div>
<xsl:apply-templates select="Root/findings/names"/>
<div style="font-weight:bold">SSNs:</div>
<xsl:apply-templates select="Root/findings/ssns"/>
<div style="font-weight:bold">DOBs:</div>
<xsl:apply-templates select="Root/findings/dobs"/>
</hmtl>
</xsl:template>
<xsl:template match="Root/findings/names">
<p>
<xsl:variable name="nmesHasData" select="boolean(normalize-space(name))"/>
<xsl:for-each select="name">
<xsl:choose>
<xsl:when test="$nmesHasData">
<ul> <xsl:apply-templates select="full"/> </ul>
</xsl:when>
<xsl:otherwise>
<xsl:text>None found</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</p>
</xsl:template>
<xsl:template match="Root/findings/ssns">
<p>
<xsl:variable name="ssnHasData" select="boolean(normalize-space(ssns))"/>
<xsl:for-each select="ssn">
<xsl:choose>
<xsl:when test="$ssnHasData">
<ul><xsl:apply-templates select="data"/></ul>
</xsl:when>
<xsl:otherwise>
<xsl:text>None found</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</p>
</xsl:template>
<xsl:template match="Root/findings/dobs">
<p>
<xsl:variable name="dobHasData" select="boolean(normalize-space(dob))"/>
<xsl:for-each select="dob">
<xsl:choose>
<xsl:when test="$dobHasData">
<ul><xsl:apply-templates select="data"/></ul>
</xsl:when>
<xsl:otherwise>
<xsl:text>None found</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</p>
</xsl:template>
</xsl:transform>
The HTML Result
<!DOCTYPE html
PUBLIC "XSLT-compat">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Person Results</title>
</head>
<div style="font-weight:bold">Alias(es):</div>
<p>
<ul>Homer J Simpson</ul>
</p>
<p>
<ul>Marge H Simpson</ul>
</p>
<div style="font-weight:bold">SSNs:</div>
<p></p>
<div style="font-weight:bold">DOBs:</div>
<p>
<ul>082967</ul>
</p>
<p>
<ul>020568</ul>
</p>
</html>
Change the template match="Root/findings/dobs" to this:
<xsl:template match="Root/findings/dobs">
<p>
<xsl:for-each select="dob">
<xsl:variable name="dobHasData" select="boolean(normalize-space(.))"/>
<xsl:choose>
<xsl:when test="$dobHasData">
<ul><xsl:apply-templates select="data"/></ul>
</xsl:when>
<xsl:otherwise>
<xsl:text>None found</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</p>
</xsl:template>
Or even more template matching like:
<xsl:template match="Root/findings/dobs">
<p>
<xsl:apply-templates select="dob"/>
</p>
</xsl:template>
<xsl:template match="dob">
<xsl:variable name="dobHasData" select="boolean(normalize-space(.))"/>
<xsl:choose>
<xsl:when test="$dobHasData">
<ul><xsl:apply-templates select="data"/></ul>
</xsl:when>
<xsl:otherwise>
<xsl:text>None found</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
And this last template could also be splitted in two short ones:
<xsl:template match="dob[normalize-space(.)]">
<ul><xsl:apply-templates select="data"/></ul>
</xsl:template>
<xsl:template match="dob[not(normalize-space(.))]">
<xsl:text>None found</xsl:text>
</xsl:template>
This is my XML code:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="2.xsl"?>
<xml_tube>
<utilizadores>
<utilizador username="Guicky" password="futurama96">
<nome>Guilherme Luís</nome>
<birthday>1996-11-28</birthday>
<foto href="guilhas.jpg"/>
</utilizador>
<utilizador username="Daisy" password="woofwoof11">
<nome>Daisy Luís</nome>
<birthday>2011-04-04</birthday>
<foto href="daisy.png"/>
</utilizador>
<utilizador username="Anabela65" password="crumble65">
<nome>Anabela Ribeiro</nome>
<birthday>1965-04-02</birthday>
<foto href="belinha.jpg"/>
</utilizador>
<utilizador username="Izzie" password="lagartixa">
<nome>Isadora Luís</nome>
<birthday>1988-06-27</birthday>
<foto href="izzie.jpg"/>
</utilizador>
</utilizadores>
<videos_pub>
<video id="Vid1" publisher="Daisy" duracao="3:37" data="2016-02-29">
<título>Who let the dogs out? - Baha Men</título>
<thumb>http://i3.ytimg.com/vi/Qkuu0Lwb5EM/hqdefault.jpg</thumb>
<descrição>My favorite song, lol.</descrição>
<hyperlink>https://www.youtube.com/watch?v=Qkuu0Lwb5EM</hyperlink>
<qualidade pixelization="1080p"/>
<qualidade pixelization="480p"/>
<likes liked="Guicky"/>
<related></related>
</video>
<video id="Vid2" publisher="Guicky" duracao="4:01" data="2016-02-29">
<título>Desiigner - Timmy Turner</título>
<thumb>http://i3.ytimg.com/vi/JzmRt2VgKYQ/hqdefault.jpg</thumb>
<descrição>Timmy Timmy Timmy Turner.</descrição>
<hyperlink>https://www.youtube.com/embed/ProbPpO_8oo</hyperlink>
<qualidade pixelization="720p"/>
<qualidade pixelization="1080p"/>
<likes liked="Anabela65"/>
<likes liked="Daisy"/>
<related></related>
</video>
<video id="Vid3" publisher="Guicky" duracao="3:47" data="2016-02-29">
<título>I'm all the way up - Fat Joe</título>
<thumb>https://www.youtube.com/watch?v=y2ak_oBeC-I</thumb>
<descrição>Nothing can stop me, I'm all the way up.</descrição>
<hyperlink>https://www.youtube.com/embed/y2ak_oBeC-I</hyperlink>
<qualidade pixelization="480p"/>
<qualidade pixelization="720p"/>
<related></related>
</video>
<video id="Vid4" publisher="Anabela65" duracao="3:21" data="2016-02-29">
<título>Putzgrilla - Sentadinha</título>
<thumb>http://i3.ytimg.com/vi/QC4JbIvIhdI/hqdefault.jpg</thumb>
<descrição>Dá uma sentadinha.</descrição>
<hyperlink>https://www.youtube.com/watch?v=QC4JbIvIhdI</hyperlink>
<qualidade pixelization="720p"/>
<likes liked="Guicky"/>
<likes liked="Daisy"/>
<related></related>
</video>
<video data="2017-01-13" duracao="02:16" id="Vid5" publisher="Izzie">
<título>Yann Tiersen - La Valse d'Amelie</título>
<thumb>http://i3.ytimg.com/vi/uzurqBnALkw/hqdefault.jpg</thumb>
<descrição>A minha música preferida.</descrição>
<hyperlink>https://www.youtube.com/watch?v=uzurqBnALkw</hyperlink>
<qualidade pixelization="720p"/>
<likes liked="Guicky"/>
<likes liked="Anabela65"/>
<related></related>
</video>
</videos_pub>
<playlist>
<lista owner="Guicky" dataIns="2016-10-24" id="PV1">
<titulo>BEST MUSIC.</titulo>
<descricao>Compilation of my favourite music videos.</descricao>
<gostosL gostouL="Guicky"/>
<links_vid vid="Vid2"/>
<links_vid vid="Vid3"/>
<administradores>
<admin ref="Guicky"/>
<admin ref="Daisy"/>
</administradores>
<editores>
<editor ref="Guicky"/>
</editores>
<subscritores>
<subs ref="Daisy"/>
<subs ref="Anabela65"/>
</subscritores>
<thumbnail link="http://i3.ytimg.com/vi/QC4JbIvIhdI/hqdefault.jpg"/>
</lista>
<lista owner="Anabela65" dataIns="2016-02-29" id="PV2">
<titulo>Sentadinha!</titulo>
<descricao>Siting lesson's with Guicky's mom!</descricao>
<links_vid vid="Vid4"/>
<administradores>
<admin ref="Anabela65"/>
<admin ref="Guicky"/>
</administradores>
<editores>
<editor ref="Anabela65"/>
</editores>
<subscritores>
<subs ref="Guicky"/>
<subs ref="Daisy"/>
</subscritores>
<thumbnail link="http://i3.ytimg.com/vi/uMK0prafzw0/hqdefault.jpg"/>
</lista>
</playlist>
<comentarios>
<comentario id="C1" refV="Vid1" user="Guicky" data="2016-10-23">
<text>AHAHAHAHA, bom vídeo.</text>
<gosto gostou="Daisy"/>
<respostas>
<texto autor="Daisy">Grande clássico!</texto>
</respostas>
</comentario>
<comentario id="C2" refL="Vid2" user="Anabela65" data="2016-10-22">
<text>Timmy timmy timmy turner...</text>
<gosto gostou="Guicky"/>
<gosto gostou="Daisy"/>
<respostas>
<texto autor="Guicky">U know it.</texto>
<resposta autor="Daisy">LOL!</resposta>
</respostas>
</comentario>
</comentarios>
</xml_tube>
And 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="http://www.w3.org/1999/xhtml">
<xsl:output method="xml" version="1.0" encoding="UTF-8"
indent="yes" />
<xsl:output doctype-public="-//W3C//DTD XHTML 1.1//EN"
doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" />
<!-- <xsl:imports href="1.xsl"/> -->
<xsl:template match="/">
<html>
<head>
<title>2.</title>
</head>
<body>
<xsl:apply-templates select="//videos_pub"/>
<!-- <xsl:apply-templates select="//comentarios"/> -->
</body>
</html>
</xsl:template>
<xsl:template match="videos_pub">
<xsl:call-template name="publisher">
<xsl:with-param name="id" select="//video/#id"/>
</xsl:call-template>
<xsl:call-template name="data">
<xsl:with-param name="id" select="//video/#id"/>
</xsl:call-template>
<xsl:call-template name="comment">
<xsl:with-param name="id" select="//video/#id"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="publisher">
<xsl:param name="id"/>
<p>
<xsl:value-of select="//video[#id = $id]/./#publisher"/>
</p>
</xsl:template>
<xsl:template name="data">
<xsl:param name="id"/>
<p>
<xsl:value-of select="//video[#id= $id]/./#data"/>
</p>
</xsl:template>
<xsl:template name="comment">
<xsl:param name="id"/>
<p>
<xsl:value-of select="count(//comentario[#refV = $id])" />
</p>
</xsl:template>
</xsl:stylesheet>
It's returning this:
Daisy
2016-02-29
0
This is what I expected it to output:
Daisy
2016-02-29
1
But it isn't returning the one. Why?
Do I have to exit the template //videos_pub?
If so, how do I do it?
I realized by doing the :
<xsl:with-param name="id" select="//video/#id"/>
I was selecting the node itself not the value of the "//video/#id" expression.
I fixed it by doing this:
<xsl:with-param name="id">
<xsl:value-of select="//video/#id"/>
</xsl:with-param>
Now my paramhas the value of the node //video/#id.
Thank you all for your answers.
You are overusing the // syntax, which is a "brute force" way of using XPath when you're not sure of a better way. You're also using "going around your elbow to get to your ***" expressions like //video[#id= $id]/./#data.
Also, I assume you want to output info for all of the videos, not just the first one.
Here is how you would do that, without all the sloppy stuff:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
<xsl:output method="xml" version="1.0" encoding="UTF-8"
indent="yes" />
<xsl:output doctype-public="-//W3C//DTD XHTML 1.1//EN"
doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" />
<!-- <xsl:imports href="1.xsl"/> -->
<xsl:template match="/">
<html>
<head>
<title>2.</title>
</head>
<body>
<ul>
<xsl:apply-templates select="xml_tube/videos_pub/video"/>
</ul>
<!-- <xsl:apply-templates select="//comentarios"/> -->
</body>
</html>
</xsl:template>
<xsl:template match="video">
<li>
<xsl:call-template name="publisher">
<xsl:with-param name="video" select="."/>
</xsl:call-template>
<xsl:call-template name="data">
<xsl:with-param name="video" select="."/>
</xsl:call-template>
<xsl:call-template name="comment">
<xsl:with-param name="id" select="#id"/>
</xsl:call-template>
</li>
</xsl:template>
<xsl:template name="publisher">
<xsl:param name="video"/>
<p>
<xsl:value-of select="$video/#publisher"/>
</p>
</xsl:template>
<xsl:template name="data">
<xsl:param name="video"/>
<p>
<xsl:value-of select="$video/#data"/>
</p>
</xsl:template>
<xsl:template name="comment">
<xsl:param name="id"/>
<p>
<xsl:value-of select="count(/xml_tube/comentarios/comentario[#refV = $id])" />
</p>
</xsl:template>
</xsl:stylesheet>
And if you want to make it really efficient, you can use an xsl:key to help count the comments:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
<xsl:output method="xml" version="1.0" encoding="UTF-8"
indent="yes" />
<xsl:output doctype-public="-//W3C//DTD XHTML 1.1//EN"
doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" />
<xsl:key name="kVideoComments" match="comentario" use="#refV" />
<!-- <xsl:imports href="1.xsl"/> -->
<xsl:template match="/">
<html>
<head>
<title>2.</title>
</head>
<body>
<ul>
<xsl:apply-templates select="xml_tube/videos_pub/video"/>
</ul>
<!-- <xsl:apply-templates select="//comentarios"/> -->
</body>
</html>
</xsl:template>
<xsl:template match="video">
<li>
<xsl:call-template name="publisher">
<xsl:with-param name="video" select="."/>
</xsl:call-template>
<xsl:call-template name="data">
<xsl:with-param name="video" select="."/>
</xsl:call-template>
<xsl:call-template name="comment">
<xsl:with-param name="id" select="#id"/>
</xsl:call-template>
</li>
</xsl:template>
<xsl:template name="publisher">
<xsl:param name="video"/>
<p>
<xsl:value-of select="$video/#publisher"/>
</p>
</xsl:template>
<xsl:template name="data">
<xsl:param name="video"/>
<p>
<xsl:value-of select="$video/#data"/>
</p>
</xsl:template>
<xsl:template name="comment">
<xsl:param name="id"/>
<p>
<xsl:value-of select="count(key('kVideoComments', $id))" />
</p>
</xsl:template>
</xsl:stylesheet>
Both of these output:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>2.</title>
</head>
<body>
<ul>
<li>
<p>Daisy</p>
<p>2016-02-29</p>
<p>1</p>
</li>
<li>
<p>Guicky</p>
<p>2016-02-29</p>
<p>0</p>
</li>
<li>
<p>Guicky</p>
<p>2016-02-29</p>
<p>0</p>
</li>
<li>
<p>Anabela65</p>
<p>2016-02-29</p>
<p>0</p>
</li>
<li>
<p>Izzie</p>
<p>2017-01-13</p>
<p>0</p>
</li>
</ul>
</body>
</html>
I have the following requirement.
input will be
———
———
<table>
<thead>
<tr>
<th></th>
<th></th>
<th></th>
…………..
…………...
</tr>
…………..
…………...
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
…………..
…………...
</tr>
…………..
…………...
</tbody>
</table>
———
———
like this multiple tables.
Now I need to create different worksheets (for workbook / Excel file) for different tables. no of worksheets depends on no of tables. I need to do this using Xslt.
No of tables are not constant it will differ.
If you have any idea please let me know. I did some research in the Internet, but I couldn’t find anything.
I wrote the following xsl. I was able to generate multiple sheets. But the table is only printed on the first sheet. I want to have the table over all sheets.
<?xml version="1.0"?>
<xsl:stylesheet
version="1.0"
xmlns="http://www.w3.org/TR/REC-html40"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:exslt="http://exslt.org/common"
xmlns:fn="http://www.w3.org/2005/02/xpath-functions"
xmlns:php="http://php.net/xsl"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:rs="urn:schemas-microsoft-com:xml-analysis:rowset"
xmlns:x="urn:schemas-microsoft-com:office:excel"
exclude-result-prefixes="xsl xsd exslt fn php SOAP-ENV rs">
<xsl:output method="html" omit-xml-declaration="yes" />
<!--
Beginning of template processing, start at document root
//-->
<xsl:variable name="pageBreakAfterTable">false</xsl:variable>
<xsl:template match="/">
</xsl:template>
<xsl:template match="/">
<xsl:text disable-output-escaping="yes"><html xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=Content-Type content="text/html; charset=windows-1252">
<meta name=ProgId content=Excel.Sheet>
<meta name=Generator content="Microsoft Excel 11">
<!--[if gte mso 9]><xml>
<x:ExcelWorkbook>
<x:ExcelWorksheets>
</xsl:text>
<xsl:for-each select="//html/body/table">
<xsl:text disable-output-escaping="yes">
<x:ExcelWorksheet>
<x:Name>Report Results</x:Name>
<x:WorksheetOptions>
<x:Selected/>
<x:ShowGridlines/>
<x:ProtectContents>False</x:ProtectContents>
<x:ProtectObjects>False</x:ProtectObjects>
<x:ProtectScenarios>False</x:ProtectScenarios>
</x:WorksheetOptions>
</xsl:text>
<xsl:element name="table">
<xsl:call-template name="processRows">
<xsl:with-param name="rows" select="./thead/tr"/>
</xsl:call-template>
<xsl:call-template name="processRows">
<xsl:with-param name="rows" select="./tbody/tr"/>
</xsl:call-template>
<xsl:call-template name="processRows">
<xsl:with-param name="rows" select="./tr"/>
</xsl:call-template>
<xsl:element name="tr"/>
</xsl:element>
<xsl:text disable-output-escaping="yes"></x:ExcelWorksheet></xsl:text>
</xsl:for-each>
<xsl:text disable-output-escaping="yes">
</x:ExcelWorksheets>
<x:ProtectStructure>False</x:ProtectStructure>
<x:ProtectWindows>False</x:ProtectWindows>
</x:ExcelWorkbook>
</xml><![endif]-->
</head>
<body></xsl:text>
<xsl:text disable-output-escaping="yes"></body></html></xsl:text>
<!-- Translate each table -->
<!-- <xsl:call-template name="processTables">
<xsl:with-param name="tables" select="//html/body/table"/>
</xsl:call-template>-->
</xsl:template>
<!-- <xsl:template name="processTables">
<xsl:param name="tables"/>
</xsl:template>-->
<xsl:template name="processRows">
<xsl:param name="rows"/>
<xsl:for-each select="$rows">
<xsl:if test="not(contains(#class,'emptyValue'))">
<xsl:element name="tr">
<xsl:attribute name="style">
<!-- Do we need to display a drill-down depth? -->
<xsl:choose>
<xsl:when test="count(./node()[contains(#class,'ds-drilldown-level-6')]) > 0">
<xsl:text>mso-outline-level:6;</xsl:text>
</xsl:when>
<xsl:when test="count(./node()[contains(#class,'ds-drilldown-level-5')]) > 0">
<xsl:text>mso-outline-level:5;</xsl:text>
</xsl:when>
<xsl:when test="count(./node()[contains(#class,'ds-drilldown-level-4')]) > 0">
<xsl:text>mso-outline-level:4;</xsl:text>
</xsl:when>
<xsl:when test="count(./node()[contains(#class,'ds-drilldown-level-3')]) > 0">
<xsl:text>mso-outline-level:3;</xsl:text>
</xsl:when>
<xsl:when test="count(./node()[contains(#class,'ds-drilldown-level-2')]) > 0">
<xsl:text>mso-outline-level:2;</xsl:text>
</xsl:when>
<xsl:when test="count(./node()[contains(#class,'ds-drilldown-level-1')]) > 0">
<xsl:text>mso-outline-level:1;</xsl:text>
</xsl:when>
</xsl:choose>
</xsl:attribute>
<xsl:for-each select="./node()">
<xsl:if test="normalize-space(.) != '' or normalize-space(#*) != ''">
<xsl:element name="td">
<xsl:if test="#colspan">
<xsl:copy-of select="#colspan"/>
</xsl:if>
<xsl:if test="#rowspan">
<xsl:copy-of select="#rowspan"/>
</xsl:if>
<xsl:if test="name(.)='td'">
<xsl:attribute name="align"><xsl:text>right</xsl:text></xsl:attribute>
</xsl:if>
<xsl:attribute name="style">
<xsl:if test="name(.)='th'">
<xsl:text> font-weight:bold;</xsl:text>
</xsl:if>
<xsl:if test="contains(#class,' red')">
<xsl:text> color:red;</xsl:text>
</xsl:if>
<xsl:if test="contains(#class,' green')">
<xsl:text> color:green;</xsl:text>
</xsl:if>
</xsl:attribute>
<xsl:value-of select="text()"/>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Your approach in disabling output escaping to do the output is not a recommended approach, not least because it makes the XML extremely hard to read. It also looks like you add HTML to your Excel spreadsheet. Excel can import HTML, I believe, but it may be better to use "XML Spreadsheet 2003" format here.
Firstly, you need to get Excel to do the hard-work for you. Open up Excel, enter some test data to represent what you want your table to look like, then save it in "XML Spreadsheet 2003" format. You can then open it in Notepad to see what Excel expects. Indeed, you can copy and paste a lot of it into Excel.
The approach you need to take in your XSLT is a template based approach. First start off by matching body elements. In the template you can output the Workbook element, and include an xsl:apply-templates to look for any table elements. For example
<xsl:template match="body">
<Workbook>
<!-- More properties here -->
<Styles>
<!-- Styles here -->
</Styles>
<xsl:apply-templates select=".//table" />
</Workbook>
</xsl:template>
Then, the template matching table will be used to output. Note the use of "Attribute Value Templates** to calculate the number of columns and rows
<xsl:template match="table">
<Worksheet ss:Name="Sheet{count(preceding::table) + 1}">
<Table ss:ExpandedColumnCount="{count(thead/tr/th)}" ss:ExpandedRowCount="{count(.//tr)}" x:FullColumns="1" x:FullRows="1" ss:DefaultRowHeight="15">
<xsl:apply-templates select=".//tr" />
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<!-- options -->
</WorksheetOptions>
</Worksheet>
</xsl:template>
You can then carry on with this approach, with templates matching tr being used to output Row elements, and templates matching td (or th) used to output Cell elements.
Try this XSLT for starters
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<xsl:output indent="yes"/>
<xsl:template match="body">
<Workbook>
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
<Author>Test</Author>
<LastAuthor>Test</LastAuthor>
<Created>2014-06-20T12:40:11Z</Created>
<Version>14.00</Version>
</DocumentProperties>
<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
<AllowPNG/>
</OfficeDocumentSettings>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
<WindowHeight>4680</WindowHeight>
<WindowWidth>16275</WindowWidth>
<WindowTopX>120</WindowTopX>
<WindowTopY>120</WindowTopY>
<ActiveSheet>1</ActiveSheet>
<ProtectStructure>False</ProtectStructure>
<ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>
<Styles>
<Style ss:ID="Default" ss:Name="Normal">
<Alignment ss:Vertical="Bottom"/>
<Borders/>
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="11" ss:Color="#000000"/>
<Interior/>
<NumberFormat/>
<Protection/>
</Style>
</Styles>
<xsl:apply-templates select=".//table" />
</Workbook>
</xsl:template>
<xsl:template match="table">
<Worksheet ss:Name="Sheet{count(preceding::table) + 1}">
<Table ss:ExpandedColumnCount="{count(thead/tr/th)}" ss:ExpandedRowCount="{count(.//tr)}" x:FullColumns="1" x:FullRows="1" ss:DefaultRowHeight="15">
<xsl:apply-templates select=".//tr" />
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageSetup>
<Header x:Margin="0.3"/>
<Footer x:Margin="0.3"/>
<PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/>
</PageSetup>
<Panes>
<Pane>
<Number>3</Number>
<ActiveRow>1</ActiveRow>
<ActiveCol>2</ActiveCol>
</Pane>
</Panes>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
</xsl:template>
<xsl:template match="tr">
<Row>
<xsl:apply-templates select="th|td" />
</Row>
</xsl:template>
<xsl:template match="th|td">
<Cell>
<Data ss:Type="String"><xsl:value-of select="." /></Data>
</Cell>
</xsl:template>
</xsl:stylesheet>
This does assumes your tables are fairly well structured. It would become more complex if you had colspan and rowspan present.
Here is the code which I wrote. Based on variable we can get the data either in single sheet or in multiple sheets.
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
<xsl:output indent="yes"/>
<!--
Beginning of template processing, start at document root
//-->
<xsl:param name="pageBreakAfterTable" select="0"/>
<xsl:template match="/">
<Workbook>
<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">
<LastAuthor>Intervolve</LastAuthor>
</DocumentProperties>
<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
<AllowPNG/>
</OfficeDocumentSettings>
<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
<WindowHeight>10880</WindowHeight>
<WindowWidth>25600</WindowWidth>
<WindowTopX>0</WindowTopX>
<WindowTopY>0</WindowTopY>
<ActiveSheet>0</ActiveSheet>
<ProtectStructure>False</ProtectStructure>
<ProtectWindows>False</ProtectWindows>
</ExcelWorkbook>
<Styles>
<Style ss:ID="Default" ss:Name="Normal">
<Alignment ss:Vertical="Bottom"/>
<Borders/>
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#000000"/>
<Interior/>
<NumberFormat/>
<Protection/>
</Style>
<Style ss:ID="s62">
<Alignment ss:Horizontal="Left" ss:Vertical="Bottom" ss:WrapText="1"/>
</Style>
<Style ss:ID="s63">
<Alignment ss:Vertical="Bottom" ss:WrapText="1"/>
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#000000" ss:Bold="1"/>
</Style>
<Style ss:ID="s64">
<Alignment ss:Horizontal="Right" ss:Vertical="Bottom" ss:WrapText="1"/>
</Style>
<Style ss:ID="s65">
<Alignment ss:Horizontal="Left" ss:Vertical="Bottom" ss:WrapText="1"/>
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Color="#DD0806"/>
</Style>
<Style ss:ID="s66">
<Alignment ss:Horizontal="Left" ss:Vertical="Bottom" ss:WrapText="1"/>
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Color="#1FB714"/>
</Style>
<Style ss:ID="s67">
<Alignment ss:Horizontal="Right" ss:Vertical="Bottom" ss:WrapText="1"/>
<NumberFormat ss:Format="Standard"/>
</Style>
<Style ss:ID="s68">
<Alignment ss:Horizontal="Right" ss:Vertical="Bottom" ss:WrapText="1"/>
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#DD0806"/>
<NumberFormat ss:Format="Standard"/>
</Style>
<Style ss:ID="s69">
<Alignment ss:Horizontal="Right" ss:Vertical="Bottom" ss:WrapText="1"/>
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#1FB714"/>
<NumberFormat ss:Format="Standard"/>
</Style>
<Style ss:ID="s70">
<Alignment ss:Horizontal="Right" ss:Vertical="Bottom" ss:WrapText="1"/>
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#1FB714"/>
<NumberFormat ss:Format="Percent"/>
</Style>
<Style ss:ID="s71">
<Alignment ss:Horizontal="Right" ss:Vertical="Bottom" ss:WrapText="1"/>
<Font ss:FontName="Calibri" x:Family="Swiss" ss:Size="12" ss:Color="#DD0806"/>
<NumberFormat ss:Format="Percent"/>
</Style>
</Styles>
<xsl:if test="$pageBreakAfterTable=1">
<xsl:apply-templates select=".//table" />
</xsl:if>
<xsl:if test="$pageBreakAfterTable=0">
<xsl:call-template name="processTables">
<xsl:with-param name="tables" select="//html/body/table"/>
</xsl:call-template>
</xsl:if>
</Workbook>
</xsl:template>
<xsl:template name="processTables">
<xsl:param name="tables"/>
<Worksheet ss:Name="Report Results">
<Table ss:ExpandedColumnCount="{count(.//tr/th)}" ss:ExpandedRowCount="{count(.//tr)}" x:FullColumns="1" x:FullRows="1" ss:DefaultRowHeight="15">
<xsl:for-each select="$tables">
<!-- <Column ss:Width="138"/>
<Column ss:Width="260"/>-->
<xsl:apply-templates select=".//tr" />
</xsl:for-each>
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageLayoutZoom>0</PageLayoutZoom>
<TopRowVisible>0</TopRowVisible>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
</xsl:template>
<xsl:template match="table">
<Worksheet ss:Name="Sheet{count(preceding::table) + 1}">
<Table ss:ExpandedColumnCount="{count(.//tr/th)}" ss:ExpandedRowCount="{count(.//tr)}" x:FullColumns="1" x:FullRows="1" ss:DefaultRowHeight="15">
<Column ss:Width="138"/>
<Column ss:Width="260"/>
<xsl:apply-templates select=".//tr" />
</Table>
<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">
<PageLayoutZoom>0</PageLayoutZoom>
<TopRowVisible>0</TopRowVisible>
<ProtectObjects>False</ProtectObjects>
<ProtectScenarios>False</ProtectScenarios>
</WorksheetOptions>
</Worksheet>
</xsl:template>
<xsl:template match="tr">
<Row>
<xsl:for-each select="./node()">
<xsl:if test="normalize-space(.) != '' or normalize-space(#*) != ''">
<Cell>
<xsl:attribute name="ss:MergeAcross">
<xsl:choose><xsl:when test="#colspan > 1"><xsl:value-of select="#colspan - 1" /></xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose>
</xsl:attribute>
<xsl:attribute name="ss:MergeDown">
<xsl:choose><xsl:when test="#rowspan > 1"><xsl:value-of select="#rowspan - 1" /></xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose>
</xsl:attribute>
<xsl:attribute name="ss:StyleID">
<xsl:choose>
<xsl:when test="name(.)='th'">s63</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="contains(#class,' green')">
<xsl:choose>
<xsl:when test="contains(text(),'%')">s70</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="contains(#class,' numeric')">s69</xsl:when>
<xsl:otherwise>s66</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="contains(#class,' red')">
<xsl:choose>
<xsl:when test="contains(text(),'%')">s71</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="contains(#class,' numeric')">s68</xsl:when>
<xsl:otherwise>s65</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>s62</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<Data>
<xsl:attribute name="ss:Type">
<xsl:choose>
<xsl:when test="contains(text(),'%')">String</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="contains(#class,' numeric')">Number</xsl:when>
<xsl:otherwise>String</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:value-of select="text()"/>
</Data>
</Cell>
</xsl:if>
</xsl:for-each>
</Row>
</xsl:template>
</xsl:stylesheet>