SiteExperts.com Logo Home | Community | Developer's Paradise | Jobs
User Groups | Site Tools | Site Information | Search

Inside Technique : Building a Content Server with XML and ASP : Rendering Files

The story.asp page is based on the ASP script introduced in our previous XML article, Building Smart Pages with ASP, XML, and XSL. The story.asp page loads an XML file, applies an XSL transformation on the server, creating HTML that is delivered to the client. If you remember the previous article, the transformation occurs in the TransformDocument function. This function takes an XML and XSL document, performs the transformation, and returns the generated HTML. Below is the version of this function we use in our content server:

function TransformDocument(sPath, srcXML, srcXSL, sDir) 
  Dim sourceFile, styleFile, source, sCache
  Dim objFSO, objFile
  sCache = sPath + sDir + "\" + srcXML + ".inc"
  Set objFSO = CreateObject("Scripting.FileSystemObject")
  if objFSO.FileExists(sCache) Then
    ' Check if cached
    Set objFile = objFSO.OpenTextFile(sCache)
    TransformDocument = objFile.readAll
    objFile.close
  else
    sourceFile = sPath + "src/" + srcXML + ".xml"
    styleFile = sPath + srcXSL
    ' Load the XML - Use Free Threaded control
    set source = Server.CreateObject("Microsoft.FreeThreadedXMLDOM")
    source.async = false
    source.load sourceFile

    ' Load the XSL
    ' Cache parsed XSL sheet
    if isempty(application(styleFile)) then
      set  style = Server.CreateObject("Microsoft.FreeThreadedXMLDOM")
      style.async = false
      style.load styleFile
      application.lock()
      set application(styleFile)=style
      application.unlock()
    else
      set style = application(styleFile)
    end if
    if (source.parseError.errorCode <> 0) then
      result = reportParseError(source.parseError)
    elseif (style.parseError.errorCode <> 0) then
      result = reportParseError(style.parseError)
    else
      on error resume next
      result = source.transformNode(style)
      if (err.number<>0) then
         result = reportRuntimeError(exception)
      else
        ' Cache generated HTML
        Set objFile = objFSO.CreateTextFile(sCache,true)
        objFile.write(result)
        objFile.close
      end if
    end if
    TransformDocument = result
  end if
  set objFile = nothing
End Function

The key change we made to the original transformDocument function is the addition of two simple caching mechanisms:

  1. Cache the parsed XSL Sheet
  2. Cache the resulting HTML to disk

Loading the same XSL sheet for each article is expensive. Instead, we share the parsed XSL document across all articles by caching it in the global application object after it is first loaded. In addition, since we assume the documents are being read much more than they are updated, we cache the generated HTML article on disk. This way, we only need to perform the transformation once for each article. All subsequent requests just return the generated HTML.

Implementation Note
If you want to store the XML component in the application or session state, you need to use the free-threaded version of the XML control (Microsoft.FreeThreadedXMLDOM). If you are only using the XML comoponent on the page itself, you should use the single-threaded version as you will get better performance (Microsoft.XMLDOM). Since you can't share objects between the two versions, you should not intermix both versions on the same page.

Since this page is both data and style agnostic, we can easily reuse this page to present any combination of XSL and XML. For this reason, we are able to easily present both the story index and the stories themselves using the same ASP page. To distinguish what page is being served, we use the querystring portion of the URL. When the user requests the page story.asp, we return the story index. When the request is of the form story.asp?storyid=n, where n is a story id, we return the actual story. The script that tests these cases is extremely simple:

iID = request.queryString("storyID")

if not isNumeric(iID) or iID="" then
  ' No story ID, return the index
  sStory = "index"
  sStyle = "src/index.xsl"
else
  ' Return a story
  sStory = iID 
  sStyle = "src/article.xsl"
end if

response.write(TransformDocument(sPath,sStory,sStyle,"CACHE"))

That's it! You have now seen the presentation portion of our content server. Next we introduce the editing portion. The editing portion is much more interesting as we manipulate the XML documents using the XML Document Object Model.