devxlogo

Learn Better Ways to Manage Data in ASP

Learn Better Ways to Manage Data in ASP

lthough you may not be able to switch to ASP.NET at your location, you can take full advantage of XML and XSLT transforms now to make your site more flexible, more robust, and in some cases, faster. In this article, you’ll see how to use XML and XSLT to display, manage, and cache data in your ASP applications.

Suppose you have a list of internal links for your site?the basis of a menu. You want to format the links down the left side of the screen as a list in a table. In other words, the HTML you need?in very plain form?looks something like this:

            

Link 1
Link 2
Link 3

Content here


The HTML above describes two tables that appear next to one another. The one on the left holds the list of links, while the one on the right holds the main site content.
Transform XML with XSLT Stylesheets
As the list of links won’t change terribly often, you could easily store them in a simple XML document. For example:

      

4

You can write an XSLT stylesheet to transform that data into HTML, for example:

                              

Then you can perform the transform on the server:

   <%@ Language=VBScript %>   <%   dim xml   dim xsl   set xml = Server.CreateObject("MSXML2.DOMDocument.4.0")   set xsl = Server.CreateObject("MSXML2.DOMDocument.4.0")   xml.load Server.MapPath(".") & "menu.xml"   xsl.load Server.MapPath(".") & "menu.xsl"   %>               <%Response.Write xml.transformNode(xsl)%>      
Author’s Note: For the code in this article, I’ve used the MSXML version 4 processor, but the code works fine with version 3. To use it with version 3, change every occurrence of Server.CreateObject(“someobjectProgID.4.0”) to Server.CreateObject(“someobjectProgID.3.0”).

Add Server-Side Caching for Speed
The simple process you’ve seen loads the XML document and XSLT stylesheets for each request. It works fineand it’s faster than retrieving the list of links from a database and then formatting it with VBScript code on the server. But there’s a problem with this methodit’s not fast enough, and you can optimize it. To do so, use the free-threaded version of the DOMDocument object to cache the XML document containing the links and the XSLT file containing the stylesheet in memory. By doing that, you avoid having to create DOMDocument objects and read the document from disk each time. Although you would normally load these objects in your global.asa file, you can just as easily load them during any page request. For example:

   <%@ Language=VBScript %>   <%   dim xml   dim xsl   dim LinkData_filename    dim appPath   appPath = Server.MapPath(".")    LinkData_filename = appPath & "menu.xml"   if isEmpty(Application("LinkData")) or _      Request("refresh") = "true" then         Response.Write "Loading from disk"         ' load the XML document       set xml = Server.CreateObject _         ("MSXML2.FreeThreadedDOMDocument.4.0")       call loadXMLFile(xml, LinkData_filename)       call updateAppVariable("LinkData", xml)    else      Response.Write "Loading from cache"      set xml = Application("LinkData")    end if
The first time a client requests this page, the server creates and stores a FreeThreadedDOMDocument object at Application scope, where it’s available for each subsequent request. You can see the difference in performance between the initial load and the cached copy by requesting the page twice (see the file testMenu2.asp in the downloadable code for the example. For the purposes of this example, I’ve made it write messages to the browser. The first time you load the page, it prints “Loading from disk,” but all subsequent times, it prints “Loading from cache.”

The loadXMLFile() function is a wrapper that displays error information if the XML file fails to load properly.

   sub loadXMLFile(xmldoc, filename)      if not xmldoc.load(filename) then         Response.Write “Error loading the file ‘” _           & filename & “‘.
” Response.Write “Description: ” & _ xmldoc.parseError.reason & “
” Response.Write “Line: ” & _ xmldoc.parseError.line & “
” Response.Write “Line position: ” _ & xmldoc.parseError.linepos & “
” Response.End end if end sub
When you update values stored in the Application object, you need to lock the Application to avoid the problem of one thread attempting to retrieve the data while another thread is changing it. Programmers sometimes forget to lock the Application object. The updateAppVariable function protects and generalizes setting Application variables:

   sub updateAppVariable(varName, value)      Application.Lock      if isObject(value) then         set Application(varname) = value      else         Application(varname) = value      end if      Application.UnLock   end sub
You use a slightly different sequence to cache XSLT stylesheets. The XSLTemplate object has a stylesheet property that accepts a FreeThreadedDOMDocument object. You create the XSLTemplate object, set its stylesheet property, and then cache the XSLTemplate at Application scope rather than the FreeThreadedDOMDocument itself. The process of loading and caching the XSLTemplate object is very similar to storing a FreeThreadedDOMDocument alone. For example, the following code loads the XSLT file that creates the list of links:

   ‘ load the list XSL file      set xsl = Server.CreateObject _     (“MSXML2.FreeThreadedDOMDocument.4.0”)   call loadXMLFile(xsl, LinkSelect_filename)   set template = Server.CreateObject _      (“MSXML2.XSLTemplate.4.0”)   set template.stylesheet = xsl   call updateAppVariable(“LinkSelect”, template)
After creating the XSLTemplate object, you use its createProcessor method to create an XSLProcessor instance that actually performs the transformation. You set the XSLProcessor’s input property to the XML file and retrieve the results via the output property.

   set template = Application(“LinkSelect”)    set proc = template.createProcessor    proc.input = xml   Response.Write proc.output
The output is a string containing the transformed XML data. XSLTemplates have a speed advantage over caching the stylesheet directly as a FreeThreadedDOMDocument object because the stylesheet is pre-compiled, rather than compiled for each use. In addition, the XSLTemplate objects make using XSLT parameters very easy, as you’ll see later in this article.
Add XML/XSLT-Based Administration
Creating the links table using cached data is measurably faster, but it has a problem. By loading the XML document from memory each time, you could change the link file and propagate the change to clients immediately. But by pulling the datafrom cache, changes you make to the file will not appear until you shut the application down and restart it. In other words, you need a way to know when to refresh the cached data. You can do that in several ways:

  • by checking the file date/time against a stored file date/time every time a page requests the file
  • by creating a method that checks a Request parameter, for example “RefreshMenu=true”
  • by creating an ASP page that lets the appropriate people update the fileand then automatically refreshes the data.
The last option is the best for non-administrative users, because using the administration page minimizes the possibility of a manually entered syntax error causing problems and eliminates the possibility of someone forgetting to update the cached data (via a Request parameter) after modifying the file. In addition, people who need to modify the data can update it from any browser that can reach the administration page. However, for administrators, it’s generally a good idea to create a Request parameter that automatically refreshes the XML and XSLT files, so that they can make changes to the XSLT templates without having to shut down the site to force the changes to appear.

The people who maintain the list of links need to be able to add, modify, and delete tags within the XML file. XSLT isn’t strictly required to build and display the user interface for list administration, but it simplifies and optimizes the code considerably, offloading otherwise messy and slow string operations in your VBScript code to the XSLT stylesheet instead.

Because the fields to add a new link are identical to the fields to modify an existing link you can use the same user interface for both operations. Therefore you only need two transformsone to display the list and one to display the data for editing, along with the appropriate controls. The following stylesheet displays the link list in alphabetical order by title. Note that you might extend this stylesheet to let users sort the links in other ways as well, for example, to display the links in the order they appear on the site (the code is in the file menuEditSelect.xsl).

                                          

The first template in the stylesheet matches the root element. The second matches the

element, selects its child elements, and sorts them by the title attribute value. The last template displays the links as anchor tags. Finally, it displays an submit button with the caption “Add” at the end of the list. For longer lists, you’d want to place the button elsewhere, so it doesn’t scroll off the screen.

When the user selects a tag, the anchor returns the id of the selected link as a QueryString parameter. The anchor tags perform “GET” requests, while a form with the method=”post” attribute performs a “POST” request. You can use the request type to determine whether the user has posted new or altered data or wants to edit or insert a link.

   select case Request.ServerVariables(“REQUEST_METHOD”)    case “POST”      ‘ perform update, add, and delete operations here   case “GET”      ‘ display the details for a link item   end select
After determining the request type, you can find out whether the user has selected a link or is requesting the initial list display by checking for the existence of the id QueryString parameter. When the parameter is missing, the user has requested the list, and the code calls the showList() method; otherwise, the user has selected a link and wants to edit that item, so the code calls the showEditForm() method, passing the string value of the id parameter.

   case “GET”      ‘ display the details for a link item      if Request.QueryString(“id”) = “” then         call showList()      else         call showEditForm _        (Cstr(Request.QueryString(“id”)), xml)      end if   end select
The showList() method loads the menuEditSelect.xsl stylesheet.

   sub showList()      set template = Application(“LinkSelect”)      set proc = template.createProcessor         proc.input=xml   end sub
The showEditForm() method also loads an XSLT template but needs to be able to select a single item (identified by id) in editable form; therefore it takes the id as the first parameter. The method also accepts an XML DOMDocument object (xmldoc) containing the source data.

   sub showEditForm(id, xmldoc)      set template = Application(“LinkEdit”)      set proc = template.createProcessor      proc.addParameter “id”, id      proc.input=xmldoc      isEditMode=true   end sub

Build the Administration User Interface
After a user elects to add or edit a link, the LinkEdit stylesheet creates the UI. The showEditForm() method retrieves the cached XSLTemplate object containing the stylesheet, creates a processor, and sets everything up for the transform. For existing link items, you pass the stylesheet the XML document and the id of the item the user wants to modify. As you can see, that’s where the XSLProcessor object’s addParameter() method comes in handyit’s much simpler than retrieving an node and setting its value using DOM methods.

In both cases, the methods set up the transform but defer running it until the response reaches the proper position in the HTML. The following HTML acts as a form container for the output of the various stylesheets:

               

<% proc.transform if isEditMode then Response.Write "Edit the title and url and then click Submit.
” Response.Write “To delete a link, click Delete.
” end if Response.write proc.output %>

After selecting a link, users can edit the title and the URL and submit the changes via the POST method by clicking the Submit button. When the request contains an update to an existing link item, the code first retrieves the item from the XML document and then assigns the updated title and URL strings to the title and URL attributes for that link element. Similarly, when a user deletes an item, the code retrieves the item and uses the DOM removeChild method to delete the item from the file. Those two operations are very straightforward.

The more interesting part happens when the user wants to add a new item. First, each tag contains a id attribute. The entire scheme rests on the ids being unique. One way to ensure unique values is to increment a number every time a user adds a new link element. The code accomplishes that by retrieving and incrementing the contents of the element at the top of the XML file every time a user clicks the Add button.

However, there’s yet another problem. The XSLT stylesheet that displays the UI expects an id parameter, and selects that item from the XML filebut when users want to add a new item, the item doesn’t exist yet. The simplest workaround is to create a new XML string containing a blank item and pass that to the stylesheet rather than the XML file containing the existing links. Here’s the code:

   Select Case Request.Form(“btnAction”)      case “Delete” ‘ user clicked the Delete button         ‘ code to delete an element here         case “Add” ‘ user clicked the Add button         ‘ get the next id value from the XML file         set N = xml.selectSingleNode(“menu/nextid”)         Response.Write N.text            ‘ set the id to that value         id = “link” & N.text                  ‘ update the nextid value in the XML file         N.text = (cstr(cint(N.Text) + 1))                  ‘ create a new link node in an empty menu file         set blankXML = Server.CreateObject _           (“MSXML2.FreeThreadedDOMDocument.4.0”)         blankXML.loadXML  “” & _        “

” ‘ show the blank edit form call showEditForm(id, blankXML) case “Submit” ‘ user clicked the Submit button ‘ code to update a link element’s attributes here End Select

By using the blank XML document, if users click the Add button and then close the browser, the main XML document’s value updates, skipping a sequential value, but nothing else happens, which makes the technique relatively safe because no one cares about skipped id values.

Using these simple techniques, you can increase the speed of your Web site, let users safely modify dynamic data, eliminate syntax errors in the data file, and change the UI easily by simply updating the XSLT stylesheets that drive the transformations. After making a change to a stylesheet, an administrator can reload the page with the QueryString parameter “refresh=true” appended to the URLand all subsequent pages will reflect the changes.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist