views:

319

answers:

2

I'm writing a simple asp page to show a team rota based on some XML. Here's the XML:

<rota>
<shift date="20091201" primary="Chan" secondary="John" notes="notes"></shift>
<shift date="20091202" primary="Mike" secondary="Alex" notes="notes"></shift>
<shift date="20091203" primary="Ross" secondary="Mike" notes="notes"></shift>
<shift date="20091204" primary="Neil" secondary="Ross" notes="notes"></shift>
</rota>

I want my asp page to show today's rota details and maybe the details for the next couple of days. Since later on I'd like to be able to set a day in the future to see who's working around then I want to be able to pass a YYYYMMDD date from the ASP to the XSL that processes the XML.

Here's the XSL I have so far, just highlighting the hardcoded 'current' date for now:

<xsl:template match="rota">
 <html>
 <head>
  <title>Team Rota</title>
  <LINK type="text/css" rel="stylesheet" href="http://www.csfb.net/homepage/global/scripts/csfb_intranet.css"/&gt; 
 </head>
 <body>
 <table border="1">
 <TR><TH>Date</TH><TH>Primary</TH><TH>Secondary</TH><TH>Notes</TH></TR>
 <xsl:for-each select="shift">
  <tr>
   <xsl:choose>
    <xsl:when test="@date = '20091203'">
     <td bgcolor='FFF0F0'><xsl:value-of select="@date"/></td>
    </xsl:when>
    <xsl:otherwise>
     <td><xsl:value-of select="@date"/></td>
    </xsl:otherwise>
   </xsl:choose>
   <td><xsl:value-of select="@primary"/></td>
   <td><xsl:value-of select="@secondary"/></td>
   <td><xsl:value-of select="@notes"/></td>
  </tr>  
 </xsl:for-each>
 </table>
 </body>
 </html>
</xsl:template>

and here's the ASP, not yet passing any parameters:

''// Load the XML
sourcefile = "rota.xml"
set source = Server.CreateObject("Microsoft.XMLDOM")
source.async = false
source.load(sourceFile)

''// Load the XSL
styleFile = Server.MapPath("rota.xsl")
set style = Server.CreateObject("Microsoft.XMLDOM")
style.async = false
style.load(styleFile)

htmltext = source.transformNode(style)
Response.Write htmltext

So how do I a) pass a parameter to the XSL and b) pick up that parameter and use it in the XSL?

Thanks for any guidance.

+1  A: 

You should declare your parameter like this:

<xsl:stylesheet ... >
  <xsl:parameter name="your_parameter"/>
  <xsl:template match="rota">
      $your_parameter = <xsl:value-of select="$your_parameter" />
  ...

And pass it like this

'// Load the XSL
styleFile = Server.MapPath("rota.xsl")
set style = Server.CreateObject("MSXML2.FreeThreadedDOMDocument.3.0")
style.async = false
style.load(styleFile)

Set template = Server.CreateObject("MSXML2.XSLTemplate.3.0")
template.stylesheet = style

Set processor = myTemplate.createProcessor()
processor.addParameter "your_parameter", "value"
processor.input = source
processor.output = Response
processor.transform()
Rubens Farias
Thanks for the swift reply. Now I'm getting: "The XSL stylesheet document must be free threaded in order to be used with the XSLTemplate object."
theaxe
updated, check it out
Rubens Farias
+3  A: 

In you xsl create a xsl:parameter at the top before all your templates.

<xsl:parameter name="showdate"/>

You can now treat this like you would a variable:-

<xsl:when test="@date = $showdate">

In order to pass a parameter in you need to use an XSL processor object which allows you to add the parameter before processing. In turn you get a processor from an instance of an XSL Template object. In turn you need a FreeThreadedDOMDocument to assign to the templates stylesheet parameter. Hence the code is more complex:-

 Dim xsl : Set xsl = CreateObject("MSXML2.FreeThreadedDOMDocument.3.0")
 xsl.async = false
 xsl.load xslFile

 Dim xml : Set xml = CreateObject("MSXML2.DOMDocument.3.0")
 xml.async = false
 xml.load sourceFile

 Dim xslTemplate : Set xslTemplate = CreateObject("MSXML2.XSLTemplate.3.0")
 xslTemplate.stylesheet = xsl;

 Dim processor : Set processor = xslTemplate.createProcessor()
 processor.addParameter "showDate", "20091203"
 processor.input = source
 processor.transform()  

 Response.Write processor.output

Its tempting to assign the Response object to the processor's output parameter which works quite well and is more efficient. However recent Service packs of MSXML have made such a technique incompatible with ASP's implementation of IStream in the Response object.

So thats how you do it officially, how I do it normally is to inject some arbitary attribute on to the source XML's root node then use a variable:-

xml.documentElement.setAttribute("_showDate", "20091203")

Now you can use a variable instead of a parameter inside your main template:-

<xsl:template match="rota">
  <xsl:variable name="showdate" select="@_showDate" />
    <html> ...
         <xsl:when test="@date = $showdate">

In this approach you can use the transform code you are already using which is much simpler.

AnthonyWJones
I used your latter suggestion and it works a treat. Thanks!
theaxe