Hopefully this will be a simple fix. I'm completely new to XSL but I've managed to get a little script that sorts my data by date. I now want to use ASP to limit this data to all entries within a month (this works by using a DateDiff() function). When I go to load in the XSL scripts output it says that my XML is malformed. Can anyone help me out here please?
Here's my XML File:
<?xml version="1.0"?>
<Rota>
<Shift>
<date>23/07/2010</date>
<title1>GM Neurosciences</title1>
<gm>Katie Cusick</gm>
<title2>Chief Operating Officer</title2>
<director>Patrick Mitchell</director>
<nurse>n/a</nurse>
</Shift>
<Shift>
<date>30/07/2010</date>
<title1>GM Specialised Medicine</title1>
<gm>Alison Watson</gm>
<title2>DDO Medicine & Cardio.</title2>
<director>Suzanne Marsello</director>
<nurse>n/a</nurse>
</Shift>
</Rota>
Here's my XSL File:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" omit-xml-declaration="no" version="1.0" />
<xsl:param name="sortBy" select="'date'"/>
<xsl:param name="strXPath" select="//Shift"/>
<开发者_如何学运维xsl:template match="/">
<xsl:apply-templates select="$strXPath">
<xsl:sort select="substring(date,7,4)"/> <!-- year sort -->
<xsl:sort select="substring(date,4,2)"/> <!-- month sort -->
<xsl:sort select="substring(date,1,2)"/> <!-- day sort -->
</xsl:apply-templates>
</xsl:template>
<xsl:template match="Shift">
<Shift>
<date><xsl:value-of select="date"/></date>
<title1><xsl:value-of select="title1"/></title1>
<gm><xsl:value-of select="gm"/><gm>
<title2><xsl:value-of select="title2"/></title2>
<director><xsl:value-of select="director"/></director>
<nurse><xsl:value-of select="nurse"/></nurse>
</Shift>
</xsl:template>
</xsl:stylesheet>
And Here's my ASP Code:
<%
Set entries = Server.CreateObject("Microsoft.XMLDOM")
Set entry = Server.CreateObject("Microsoft.XMLDOM")
Set xml = Server.CreateObject("Microsoft.XMLDOM")
Set xsl = Server.CreateObject("Microsoft.XMLDOM")
Set newxml = Server.CreateObject("Microsoft.XMLDOM")
xml.async = False
xml.load (Server.MapPath("rota.xml"))
xsl.async = False
xsl.load(Server.MapPath("indexrota.xsl"))
newxml.async = False
newxml.load(xml.transformNode(xsl))
set entries = newxml.getElementsbyTagName("Shift")
noOfEntries = entries.length
startDate = "15/07/2010"
LastDate = DateAdd("m",1,date())
Response.Write("<table><tr><th>Date</th><th>Title</th><th>GM</th><th>Title</th><th>Director</th><th>Nurse / Matron</th></tr>")
For i = 0 To (noOfEntries - 1)
Set entry = entries.item(i)
If isDate(entry.childNodes(0).text) Then
meh = CDate(entry.childNodes(0).text)
beginning = DateDiff("d", meh, startDate)
ended = DateDiff("d", meh, LastDate)
If beginning + 1 <= 0 And ended >= 0 Then
Response.Write("<tr>"&_
"<td>" & entry.childNodes(0).text & "</td>"&_
"<td>" & entry.childNodes(1).text & "</td>"&_
"<td>" & entry.childNodes(2).text & "</td>"&_
"<td>" & entry.childNodes(3).text & "</td>"&_
"<td>" & entry.childNodes(4).text & "</td>"&_
"<td>" & entry.childNodes(5).text & "</td>"&_
"</tr>")
End If
End If
Next
Response.Write("</table>")
%>
I'm sure it's a case of the XSL because the ASP has worked perfecton the XML before
There are two problems with your XSL.
Firstly, where you copy the gm element, you have not correctly closed off the gm tag.
<gm><xsl:value-of select="gm"/><gm>
This should become
<gm><xsl:value-of select="gm"/></gm>
Secondly, althuogh you are copying the Shift elements, your resultant XML does not contain a root element. You need to put a Rota element outside your xsl:apply-templates call
<xsl:template match="/">
<Rota>
<xsl:apply-templates select="$strXPath">
<xsl:sort select="substring(date,7,4)"/> <!-- year sort -->
<xsl:sort select="substring(date,4,2)"/> <!-- month sort -->
<xsl:sort select="substring(date,1,2)"/> <!-- day sort -->
</xsl:apply-templates>
</Rota>
</xsl:template>
Note that you can simplify the copying of the Shift element, simply by doing this
<xsl:template match="Shift">
<xsl:copy-of select="." />
</xsl:template>
There is also a problem with the ASP code. The line newxml.load(xml.transformNode(xsl)) is incorrect. Because transformNode returns a string containing the XML, you really need to do the following
newxml.loadXml(xml.transformNode(xsl))
Use load when loading xml from a file. Use loadXml when loading a string containing Xml
This stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Rota">
<xsl:copy>
<xsl:apply-templates select="@*|node()">
<xsl:sort select="substring(date,7)"/>
<xsl:sort select="substring(date,4,2)"/>
<xsl:sort select="substring(date,1,2)"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
With this input:
<Rota>
<Shift>
<date>30/07/2010</date>
<title1>GM Specialised Medicine</title1>
<gm>Alison Watson</gm>
<title2>DDO Medicine & Cardio.</title2>
<director>Suzanne Marsello</director>
<nurse>n/a</nurse>
</Shift>
<Shift>
<date>23/07/2010</date>
<title1>GM Neurosciences</title1>
<gm>Katie Cusick</gm>
<title2>Chief Operating Officer</title2>
<director>Patrick Mitchell</director>
<nurse>n/a</nurse>
</Shift>
</Rota>
Output:
<Rota>
<Shift>
<date>23/07/2010</date>
<title1>GM Neurosciences</title1>
<gm>Katie Cusick</gm>
<title2>Chief Operating Officer</title2>
<director>Patrick Mitchell</director>
<nurse>n/a</nurse>
</Shift>
<Shift>
<date>30/07/2010</date>
<title1>GM Specialised Medicine</title1>
<gm>Alison Watson</gm>
<title2>DDO Medicine & Cardio.</title2>
<director>Suzanne Marsello</director>
<nurse>n/a</nurse>
</Shift>
</Rota>
Also, this stylesheet works:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()">
<xsl:sort select="substring(date,7)"/>
<xsl:sort select="substring(date,4,2)"/>
<xsl:sort select="substring(date,1,2)"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Note: Correct substring. I change input order because default order is ascending. If you want descendent order add to xsl:sort
this attribute order="descending"
.
EDIT: Reverted wrong substring. Also, why don't you do all with XSLT? As example, this stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="startDate" select="20100715"/>
<xsl:param name="endDate" select="$startDate + 100"/>
<xsl:template match="Rota">
<table>
<tr>
<th>Date</th>
<th>Title</th>
<th>GM</th>
<th>Title</th>
<th>Director</th>
<th>Nurse / Matron</th>
</tr>
<xsl:apply-templates select="Shift[concat(substring(date,7),
substring(date,4,2),
substring(date,1,2))
>= $startDate]
[$endDate >=
concat(substring(date,7),
substring(date,4,2),
substring(date,1,2))]">
<xsl:sort select="substring(date,7)"/>
<xsl:sort select="substring(date,4,2)"/>
<xsl:sort select="substring(date,1,2)"/>
</xsl:apply-templates>
</table>
</xsl:template>
<xsl:template match="Shift">
<tr>
<xsl:apply-templates/>
</tr>
</xsl:template>
<xsl:template match="Shift/*">
<td>
<xsl:value-of select="."/>
</td>
</xsl:template>
</xsl:stylesheet>
Output:
<table>
<tr>
<th>Date</th>
<th>Title</th>
<th>GM</th>
<th>Title</th>
<th>Director</th>
<th>Nurse / Matron</th>
</tr>
<tr>
<td>23/07/2010</td>
<td>GM Neurosciences</td>
<td>Katie Cusick</td>
<td>Chief Operating Officer</td>
<td>Patrick Mitchell</td>
<td>n/a</td>
</tr>
<tr>
<td>30/07/2010</td>
<td>GM Specialised Medicine</td>
<td>Alison Watson</td>
<td>DDO Medicine & Cardio.</td>
<td>Suzanne Marsello</td>
<td>n/a</td>
</tr>
</table>
精彩评论