One Script to Manage the Site

This site has been designed to be relatively simple with ease of future maintenance in mind. Basically, it contains two levels of pages:

For this design to work efficiently, the script must:

On this Web site, this result is achieved through one relatively simple ASP script that is saved as an include file (called "managexmlxsl.inc") and called by all the other asp pages on the site. This include file is shown in the first example below (ASP Using VBScript). It's fully commented so one can read through it and see how it works. Similar examples are also provided for other Web environments (ASP Using C#, PHP, JSP, Java Filter, and ColdFusion). All of these samples use one script (according to the syntax and rules of their coding language) that is saved as an include file to manage the entire Web site. You will see many similarities among these different scripts. The important point is that the XML, XSL and graphic files within the site do not change at all and are processed the same by all these scripts -- making for transportable Web content that can be delivered in virtually any Web environment.


ASP Using VBScript (as used in this Web Site)
				
<%
' ******************************************************************************************
' COPYRIGHT NOTICE:
' Copyright 2006 Center for Technology in Government.
' The Center grants permission to use and modify this software code free of charge provided  
' this copyright notice is included. By using this code you agree to indemnify the Center from 
' any liability that might arise from its use. Selling the code is expressly forbidden.
' ******************************************************************************************

' ******************************************************************************************
' THIS INCLUDE FILE IS CALLED BY ALL THE ASP FILES IN THIS WEBSITE
' AND IT CONTROLS ALL THE WEBSERVER RETRIEVAL OF FOLDERS/FILES
' IT SUPPORTS A DIRECTORY STRUCTURE BASED ON THE MAIN NAVIGATION
' TABS OF THE WEBSITE; IT PROCESSES MUTLIPLE XML FILES WITH JUST A
' FEW XSL FILES GEARED TO LEVELS WITHIN THE WEBSITE; AND IT PASSES
' PARAMETERS FROM THE URL REQUEST QUERY STRING TO THE XSL FILES
' ******************************************************************************************

 Dim oXML, oXSL,strName,xml,xsl,template,processor,url,passname,fs

' ******************************************************************************************
' First, get the url string so you can manipulate it as a string 
' and direct the web server to the correct directory and file
' uses PATH_INFO instead of HTTP_URL because PATH_INFO
' trims off everything after a ? in the url
' Uses url variable to find path to the correct .xml file 
' Uses passname variable to pass name parameter to the XSL file 

Set fs=Server.CreateObject("Scripting.FileSystemObject") 
url=Request.ServerVariables("PATH_INFO")
passname=Request.ServerVariables("PATH_INFO")

url=fs.GetBaseName(url)
passname=fs.GetBaseName(passname)

' ******************************************************************************************
' These initial IF conditions read the URL to see the xxxxx.asp reference
' If it is an Index.asp or index.asp, then it directs webserver to the 
' index file on the root directory; If it is not index.asp, then it 
' directs the webserver to the appropriate sub-directory folder and file
' in standard format: subdirectory/subdirectory

If url="Index" Then
    url="index"
ElseIf url="index" Then	
    url=url
Else
    url=url&"/"&url
End If

' ******************************************************************************************
' Defines 2 parameters to pass to XSL files
' If there is a sub parameter in the query string, 
' it retrieves the appropriate xml file from the appropriate subdirectory
' and processes it with the level2 xsl file and passes the sub parameter
' to the level2.xsl file
' If no sub parameters, it uses the level1.xsl file
' We also pass the script file extension ".asp" to XSL file so that 
' extensions are not hardcoded in the navigation links in the xml or xsl files. 

param1 = Request.QueryString("sub")
param2=passname

Set xml = Server.CreateObject("MSXML2.FreeThreadedDOMDocument.3.0")
xml.async = false
xml.load (Server.MapPath(url & ".xml"))
Set xsl = Server.CreateObject("MSXML2.FreeThreadedDOMDocument.3.0")
xsl.async = false

If param1<> "" then
	xsl.load (Server.MapPath("level2.xsl"))
Else
	xsl.load (Server.MapPath("level1.xsl"))
End If

Set template = Server.CreateObject("MSXML2.XSLTemplate")
template.stylesheet = xsl 
set processor = template.createProcessor()
processor.input = xml

processor.addParameter "extension", ".asp"
	   
If param1<> "" then
	processor.addParameter "sub", param1 
End If 
	  
If param2<> "" then
	processor.addParameter "name", param2
End If 

processor.transform()
Response.write (processor.output)   
   
%>


		
			

ASP.NET Using C#
				
<%--
*******************************************************************************************
* COPYRIGHT NOTICE:
* Copyright 2006 Center for Technology in Government.
* The Center grants permission to use and modify this software code free of charge provided  
* this copyright notice is included. By using this code you agree to indemnify the Center from 
* any liability that might arise from its use. Selling the code is expressly forbidden.
* ******************************************************************************************

******************************************************************************************
' THIS INCLUDE FILE IS CALLED BY ALL THE ASPX FILES IN THIS WEBSITE
' AND IT CONTROLS ALL THE WEBSERVER RETRIEVAL OF FOLDERS/FILES
' IT SUPPORTS A DIRECTORY STRUCTURE BASED ON THE MAIN NAVIGATION
' TABS OF THE WEBSITE; IT PROCESSES MUTLIPLE XML FILES WITH JUST A
' FEW XSL FILES GEARED TO LEVELS WITHIN THE WEBSITE; AND IT PASSES
' PARAMETERS FROM THE URL REQUEST QUERY STRING TO THE XSL FILES
******************************************************************************************
--%>

<%@ Page Language="C#" Debug="true" %>

<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Xml.Xsl" %>
<%@ Import Namespace="System.Xml.XPath" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Text" %>

<script language="C#" runat="server">

/* This function is called every time when aspx page load */
public void Page_Load(Object sender, EventArgs E) 
{ 

/******************************************************************************************
' First, get the url string so you can manipulate it as a string 
' and direct the web server to the correct directory and file
' uses PATH_INFO instead of HTTP_URL because PATH_INFO
' trims off everything after a ? in the url
' Uses url variable to find path to the correct .xml file 
******************************************************************************************/
string url=Request.CurrentExecutionFilePath;
url=Path.GetFileNameWithoutExtension(url);
string name=url;
if( url.Equals("Index") || url.Equals("index") )
    url="index";
else
    url=url + "/" + url;

/******************************************************************************************
' Get HttpRequest parameters
' If there is a sub parameter in the query string, 
' it retrieves the appropriate xml file from the appropriate subdirectory
' and processes it with the level2 xsl file and passes the sub parameter
' to the level2.xsl file
' If no sub parameters, it uses the level1.xsl file
' We also pass the script file extension ".aspx" to the XSL file
' In this way we don't have to hardcode the navigation link in xml or xsl file. 
******************************************************************************************/
XsltArgumentList args = new XsltArgumentList();
args.AddParam("extension","",".aspx");

string xmlPath;
string xslPath; 
xmlPath = Server.MapPath(url + ".xml");

string subsection = Request.QueryString["sub"];

if(subsection == null)
   xslPath = Server.MapPath("level1.xsl"); 
else
{	
  xslPath = Server.MapPath("level2.xsl"); 
  args.AddParam("sub","",subsection);
}

FileStream fs = new FileStream(xmlPath,FileMode.Open,FileAccess.Read);
StreamReader reader = new StreamReader(fs,Encoding.UTF8);
XmlTextReader xmlReader = new XmlTextReader(reader);

//Instantiate the XPathDocument Class
XPathDocument doc = new XPathDocument(xmlReader);

//Instantiate the XslTransform Class
XslTransform xslDoc = new XslTransform();
xslDoc.Load(xslPath);
xslDoc.Transform(doc,args,Response.Output);

//Close Readers
reader.Close();
xmlReader.Close();
}

</script>
 		
			

PHP
				
<?php

/*******************************************************************************************
* COPYRIGHT NOTICE:
* Copyright 2006 Center for Technology in Government.
* The Center grants permission to use and modify this software code free of charge provided  
* this copyright notice is included. By using this code you agree to indemnify the Center from 
* any liability that might arise from its use. Selling the code is expressly forbidden.
* ******************************************************************************************

* ******************************************************************************************
* THIS INCLUDE FILE IS CALLED BY ALL THE PHP FILES IN THIS WEBSITE
* AND IT CONTROLS ALL THE WEBSERVER RETRIEVAL OF FOLDERS/FILES
* IT SUPPORTS A DIRECTORY STRUCTURE BASED ON THE MAIN NAVIGATION
* TABS OF THE WEBSITE; IT PROCESSES MUTLIPLE XML FILES WITH JUST A
* FEW XSL FILES GEARED TO LEVELS WITHIN THE WEBSITE; AND IT PASSES
* PARAMETERS FROM THE URL REQUEST QUERY STRING TO THE XSL FILES
* ******************************************************************************************/

/*******************************************************************************************
* First, get the url string so you can manipulate it as a string 
* and direct the web server to the correct directory and file
* uses SCRIPT_NAME instead of HTTP_URL because SCRIPT_NAME
* trims off everything after a ? in the url
* Uses url variable to find path to the correct .xml file 
*******************************************************************************************/

$url = $_SERVER["SCRIPT_NAME"] ;
$url = basename($url,".php");

/******************************************************************************************
* These initial IF conditions read the URL to see the xxxxx.php reference
* If it is an Index.php or index.php, then it directs webserver to the 
* index file on the root directory; If it is not index.php, then it 
* directs the webserver to the appropriate sub-directory folder and file
* in standard format: subdirectory/subdirectory
******************************************************************************************/

if($url=="Index" || $url=="index")
{
  $url = "index";
}
else
{
  $url = $url."/".$url;
}

/******************************************************************************************
* Defines 2 parameters to pass to XSL files
* If there is a sub parameter in the query string, 
* it retrieves the appropriate xml file from the appropriate subdirectory
* and processes it with the level2 xsl file and passes the sub parameter
* to the level2.xsl file
* If no sub parameters, it uses the level1.xsl file
* We also pass the script file extension ".php" to XSL file
* In this way we don't have to hardcode the navigation link in xml or xsl file. 
******************************************************************************************/

$param1 = $_GET["sub"];

/* load the xml file and stylesheet as domdocuments */
$inputdom = new DomDocument();
$inputdom->load($url.".xml");

$xsl = new DomDocument();
if ($param1!="")
{
  $xsl->load("level2.xsl");
}
else 
  $xsl->load("level1.xsl");

/* create the processor and import the stylesheet */
$proc = new XsltProcessor();
$xsl = $proc->importStylesheet($xsl);

if($param1 !="")
{
  $proc->setParameter(null, "sub", $param1);
}

$proc->setParameter(null, "extension", ".php"); 

/* transform and output the xml document */
$newdom = $proc->transformToDoc($inputdom);
print $newdom->saveXML();

?> 
		
			

JSP
				
<%-- 
*******************************************************************************************
* COPYRIGHT NOTICE:
* Copyright 2006 Center for Technology in Government.
* The Center grants permission to use and modify this software code free of charge provided  
* this copyright notice is included. By using this code you agree to indemnify the Center from 
* any liability that might arise from its use. Selling the code is expressly forbidden.
* ******************************************************************************************

* ******************************************************************************************
* THIS INCLUDE FILE IS CALLED BY ALL THE JSP FILES IN THIS WEBSITE
* AND IT CONTROLS ALL THE WEBSERVER RETRIEVAL OF FOLDERS/FILES
* IT SUPPORTS A DIRECTORY STRUCTURE BASED ON THE MAIN NAVIGATION
* TABS OF THE WEBSITE; IT PROCESSES MUTLIPLE XML FILES WITH JUST A
* FEW XSL FILES GEARED TO LEVELS WITHIN THE WEBSITE; AND IT PASSES
* PARAMETERS FROM THE URL REQUEST QUERY STRING TO THE XSL FILES
* ******************************************************************************************
--%>

<%-- Must specify the jsp tag library -- xtags and make sure it has been installed correctly   --%>
<%@ taglib uri="http://jakarta.apache.org/taglibs/xtags-1.0" prefix="xtags" %>

<%-- 
*******************************************************************************************
* First, get the url string so you can manipulate it as a string 
* and direct the web server to the correct directory and file
* uses getServletPath instead of HTTP_URL because SgetServletPath
* trims off everything after a ? in the url
* Uses path variable to find path to the correct .xml file 
* Uses subsection variable to pass  parameter to the XSL file 
*******************************************************************************************
 --%>
 
 <%@ page import=" java.io.File" %>
<% 
    String path = request.getServletPath() ; 
    File urlpath = new File(path);
    path = urlpath.getName();
    path = path.replaceAll(".jsp","");
%>

<% String subsection = request.getParameter("sub") ;%>


<% 
   if ( path.compareToIgnoreCase("index") == 0 ) 
   {
%>
     <xtags:style  xml="index.xml" xsl="level1.xsl">
         <xtags:param name="extension" value=".jsp"/>
     </xtags:style>
<%
   }
   else 
   { 
       if(subsection == null)
        {
 %>
         <xtags:style  xml="<%= path + "/" + path + ".xml"  %>" xsl="level1.xsl">
         <xtags:param name="extension" value=".jsp"/>
          </xtags:style>
<%
        }
       else
        { 
 %>
         <xtags:style  xml="<%= path + "/" + path + ".xml"  %>" xsl="level2.xsl">
         <xtags:param name="sub" value="<%= subsection %>"/>
         <xtags:param name="extension" value=".jsp"/>
          </xtags:style>

<%
        }
   }
%>
 
		
			

Java Filter
				
/*******************************************************************************************
* COPYRIGHT NOTICE:
* Copyright 2006 Center for Technology in Government.
* The Center grants permission to use and modify this software code free of charge provided  
* this copyright notice is included. By using this code you agree to indemnify the Center from 
* any liability that might arise from its use. Selling the code is expressly forbidden.
* ******************************************************************************************

* ******************************************************************************************
* THIS JAVA FILE IMPLEMENTS A JAVA FILTER 
* WHICH IS CONNECTED TO ALL THE JSP FILES IN THIS WEBSITE
* AND IT CONTROLS ALL THE WEBSERVER RETRIEVAL OF FOLDERS/FILES
* IT SUPPORTS A DIRECTORY STRUCTURE BASED ON THE MAIN NAVIGATION
* TABS OF THE WEBSITE; IT PROCESSES MUTLIPLE XML FILES WITH JUST A
* FEW XSL FILES GEARED TO LEVELS WITHIN THE WEBSITE; AND IT PASSES
* PARAMETERS FROM THE URL REQUEST QUERY STRING TO THE XSL FILES
* *****************************************************************************************/

import java.io.*;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public  class ManageXMLXSL implements Filter 
{

   private FilterConfig filterConfig = null;

   public void init(FilterConfig filterConfig) throws ServletException 
   {
      this.filterConfig = filterConfig;
   }


   public void destroy() 
   {
      this.filterConfig = null;
   }

   /*******************************************************************************************
     This doFilter method is the key function which do all the required work
   *******************************************************************************************/
   public void doFilter(ServletRequest request, 
          ServletResponse response, FilterChain chain)
           throws IOException, ServletException 
   {

     String contentType;
     contentType = "text/html";

     String styleSheet;
     String xmlData;
     String sub = null;

     /***********************************************************************
     * First, get the url string so you can manipulate it as a string 
     * and direct the web server to the correct directory and file
     * uses getServletPath instead of HTTP_URL because getServletPath
     * trims off everything after a ? in the url
     * Uses path variable to find path to the correct .xml file 
     * Uses subsection variable to pass  parameter to the XSL file 
     ************************************************************************/
     String path = ((HttpServletRequest)request).getServletPath() ; 
     File urlpath = new File(path);
     path = urlpath.getName();
     path = path.replaceAll(".jsp","");
     String subsection = request.getParameter("sub") ;

     /* According to requested link, and retrieve related xml data and xsl stysheet */
     if ( path.compareToIgnoreCase("index") == 0 ) 
     {
       xmlData = "index.xml";
       styleSheet = "level1.xsl";
       name = "index";
     }
     else 
     { 
       xmlData = path + "/" + path + ".xml";
       name = path;
       if(subsection == null)
        {
            styleSheet = "level1.xsl";
        }
       else
        { 
            styleSheet = "level2.xsl";  
            sub = subsection;
        }

     }

     response.setContentType(contentType);

     /* set xml data source */
     String stylePath =filterConfig.getServletContext().getRealPath(styleSheet);
     Source styleSource = new StreamSource(stylePath);

     /* set XSL style sheet */
     String xmlPath =filterConfig.getServletContext().getRealPath(xmlData);
     Source xmlSource = new StreamSource(xmlPath);

     PrintWriter out = response.getWriter();

     chain.doFilter(request, response);

     /* Do the translation, using parameter and data path info */
     try 
     {
      TransformerFactory transformerFactory =TransformerFactory.newInstance();
      Transformer transformer = transformerFactory.newTransformer(styleSource);
      transformer.setParameter("extension", ".jsp") ;
      if(sub!=null)transformer.setParameter("sub", sub) ;        
      CharArrayWriter caw = new CharArrayWriter();
      StreamResult result  = new StreamResult(caw);
      transformer.transform(xmlSource, result);
      response.setContentLength(caw.toString().length());
      out.write(caw.toString());
     } 
     catch(Exception ex) 
     {
      out.println(ex.toString());
      //out.write(wrapper.toString());
     }

  }  //End of doFilter

}  //End of class
 		
			

ColdFusion
				
<!---
*******************************************************************************************
* COPYRIGHT NOTICE:
* Copyright 2006 Center for Technology in Government.
* The Center grants permission to use and modify this software code free of charge provided  
* this copyright notice is included. By using this code you agree to indemnify the Center from 
* any liability that might arise from its use. Selling the code is expressly forbidden.
* ******************************************************************************************

* ******************************************************************************************
* THIS INCLUDE FILE IS CALLED BY ALL THE COLDFUSION FILES IN THIS WEBSITE
* AND IT CONTROLS ALL THE WEBSERVER RETRIEVAL OF FOLDERS/FILES
* IT SUPPORTS A DIRECTORY STRUCTURE BASED ON THE MAIN NAVIGATION
* TABS OF THE WEBSITE; IT PROCESSES MUTLIPLE XML FILES WITH JUST A
* FEW XSL FILES GEARED TO LEVELS WITHIN THE WEBSITE; AND IT PASSES
* PARAMETERS FROM THE URL REQUEST QUERY STRING TO THE XSL FILES
* ******************************************************************************************
--->

<!--- 	
*******************************************************************************************
* Declares the sub parameter which may be passed in the URL Query String
* and is used to control processing of XSL sheets
* ******************************************************************************************
--->
<CFPARAM NAME="sub" DEFAULT="missing">

<!--- 	
*******************************************************************************************
* First, get the url string so you can manipulate it as a string 
* and direct the web server to the correct directory and file
* Parses the SCRIPT_NAME from the CGI Environment Variables to get 
* the name of the folder/file to access; stripgs the .cfm 
* extension, and replaces \ with / to build a path to the file
* that Cold Fusion will understand. Also strips the / to get 
* a file name that can be passed as a "name" parameter to the XSL
* sheet for processing
*******************************************************************************************
--->
<cfset fullStringVar = #Replace(cgi.SCRIPT_NAME,'.cfm', '','all')#>
<cfset fullStringpathVar = #Replace(fullStringVar,'/', '\','all')#>
<cfset fullStringNameVar = #Replace(fullStringVar,'/', '','all')#>

<!---	
*******************************************************************************************
* Determines if it's the index page or not that's being referenced in the 
* user's URL and then builds the path to the appropriate XML file 
* which it stores in a ColdFusion string
*******************************************************************************************
--->
<cfif cgi.SCRIPT_NAME is "/index.cfm">
	<cfset concatXML = "C:\CFusionMX7\wwwroot" & fullStringpathVar & ".xml">
<cfelse>
	<cfset concatXML = "C:\CFusionMX7\wwwroot" & fullStringpathVar & fullStringpathVar & ".xml">
</cfif>
<cffile action="read" file="#concatXML#" variable="mydoc">

<!---
*******************************************************************************************
* Determines if there is a sub parameters in the user's URL or not and 
* selects the appropriate XSL file to process the XML page
*******************************************************************************************
--->
<cfif sub is not "missing" and sub is not "">
	<cffile action="read" file="C:\CFusionMX7\wwwroot\level2.xsl" variable="xslDoc">
<cfelse>
	<cffile action="read" file="C:\CFusionMX7\wwwroot\level1.xsl" variable="xslDoc">
</cfif>
	
<!---
*******************************************************************************************
* Puts the parameters that will be used by the XSL files into a ColdFusion 
* structure that can then be passed to the XSL files via the XmlTransform 
* function
*******************************************************************************************
--->
<cfscript>
xslParams = StructNew();
StructInsert(xslParams, "sub", #sub#);
StructInsert(xslParams, "name", #fullStringNameVar#);
StructInsert(xslParams, "extension", '.cfm');
</cfscript>

<!---
*******************************************************************************************
* Runs the XMLTransform function to load the XML and XSL files, pass the 
* appropriate parameters to the XSL, and produce the HTML output
*******************************************************************************************
--->
<cfset transformedXML = XmlTransform(mydoc, xslDoc, xslParams)>
<cfoutput> #transformedXML# </cfoutput>