Universal data management and serving using pure HTML. However, in order to collect data, you need a data repository. To avoid many of the problems that come with using a database server, you can collect this data in XML. Here is the basic structure of our project:
<user>
<first_name/>
<last_name/>
<mi/>
</user>
I initially limited the data to first name, last name and middle. The basic idea behind this page is that user information is obtained in this page. After the user information needs are satisfied, the process must be moved to the next logical collection step. To keep things simple, I will wrap the user functionality into an ASP class.
Function Coalesce(vVar, vAlt)
If vVal = "" Or VarType(vVal) = 1 Or VarType(vVal) = 0 Then
Coalesce = vAlt
Else
Coalesce = vVal
End If
End Function
Class CUser
Private m_SQL, m_DOM
Public Property Get DOM()
Set DOM = m_DOM
End Property
Public Sub saveUser()
m_SQL.save "save_user", m_DOM
End Sub
Public Function validate()
m_DOM.loadXML "<root>" & m_SQL.validateUser(m_DOM) & "</root>"
If Not m_DOM.selectSingleNode("//error") Is Nothing Then
validate=False
Else
validate=True
End If
End Function
Private Sub collectData(dom, oCollection)
Dim nItem, node, parent_node, n, sKey
For nItem = 1 To oCollection.Count
sKey = oCollection.Key(nItem)
Set parent_node = dom.selectSingleNode("//" & sKey & "s")
If Not parent_node Is Nothing Then
For n = 1 To oCollection(sKey).Count
Set node = parent_node.selectSingleNode(sKey & _
"[string(.)='" &
oCollection(sKey)(n) & "']")
If node Is Nothing Then
Set node = dom.createNode(1, sKey, "")
Set node = parent_node.appendChild(node)
End If
node.text = Coalesce(oCollection(sKey)(n), "")
Next
Else
Set node = dom.selectSingleNode("//" & sKey)
If Not Node Is Nothing Then _
node.text = Coalesce(oCollection(sKey), "")
End If
Next
End Sub
Private Sub Class_Initialize()
Set m_SQL = New CSQL
Set m_DOM = Server.CreateObject("MSXML2.DOMDocument")
m_DOM.async = False
If VarType(Request ("txtUserXML")) = 0 Or Request ("txtUserXML") = "" Then
m_DOM.loadXML Request("txtUserXML")
Else
m_DOM.load "<root>" & Server.MapPath("user.xml") & "</root>"
End If
collectData m_DOM, Request.Form
collectData m_DOM, Request.QueryString
End Sub
Private Sub Class_Terminate()
Set m_SQL = Nothing
Set m_DOM = Nothing
End Sub
End Class
Class CSQL
Private m_DAL, m_Stream
Public Function save(sStoredProc, oDOM)
'adVarChar = 200
m_DAL.RunSP Array(m_DAL.mp("@xml_param", 200, 8000, oDOM.xml))
End Function
Public Function validateUser(oDOM)
Set m_Stream = m_DAL.RunSPReturnStream("validate_user", Array(_
m_DAL.mp("@xml_param", 200, 8000, oDOM.xml)))
validateUser = m_Stream.ReadText(-1)
m_Stream.Close
End Function
Private Sub Class_Initialize()
Set m_DAL = Server.CreateObject("MyPkg.MyDAL")
m_DAL.GetConnection "some connection string"
Set m_Stream = Server.CreateObject("ADODB.Stream")
End Sub
Private Sub Class_Terminate()
Set m_DAL = Nothing
Set m_Stream = Nothing
End Sub
End Class
The CSQL class is built based on a data access layer (m_DAL) component MyPkg.MyDAL. This component is built based on the Fitch and Mather DAL components, which can be found on MSDN. This way we build a bridge between SQL Server and your code.
When the CUser object is initialized, it collects the Request data and uses the collectData() subfunction to put the collected data into a corresponding node in the UserDOM. (The code I won't explain because it's fairly easy to understand on its own.) After collecting the data (or not), we'll use XSL to transform the data content into a layout.
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl=http://www.w3.org/1999/XSL/Transform
version="1.0">
<xsl:output method="html"/>
<xsl:template match="/">
<xsl:if test="//error">
<font color="red">*Information in red is required<br/></font>
</xsl:if>
<xsl:apply-templates select="//user"/>
</xsl:template>
<xsl:template match="user">
<font>
<xsl:attribute name="color">
<xsl:choose>
<xsl:when test="//error[.='first name']">red</xsl:when>
<xsl:otherwise>black</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
First Name:
</font>
<input type="text" name="first_name">
<xsl:attribute name="value"><xsl:value-of
select="first_name"/></xsl:attribute>
</input><br/>
<font>
<xsl:attribute name="color">
<xsl:choose>
<xsl:when test="//error[.='mi']">red</xsl:when>
<xsl:otherwise>black</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
MI:
</font>
<input type="text" name="mi">
<xsl:attribute name="value"><xsl:value-of select="mi"/></xsl:attribute>
</input><br/>
<font>
<xsl:attribute name="color">
<xsl:choose>
<xsl:when test="//error[.='last_name']">red</xsl:when>
<xsl:otherwise>black</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
Last Name:
</font>
<input type="text" name="last_name">
<xsl:attribute name="value"><xsl:value-of
select="last_name"/></xsl:attribute>
</input><br/>
</xsl:template>
</xsl:stylesheet>
This stylesheet will convert content into a layout. Error checking is important, and stored procedures check data by determining whether it needs processing. Returns an "errors" node for each field that cannot be empty but does not have data populated. The output of this XML is roughly as follows:
<user>. . .</user><errors><error>first_name</error>. . .</errors>
This stylesheet will transform content into layout. Error checking is important, and stored procedures check data by determining whether it needs processing. Returns an "errors" node for each field that cannot be empty but does not have data populated. The output of this XML is roughly as follows:
<user>. . .</user><errors><error>first_name</error>. . .</errors>
Note that if there is an error matching the node name, the output produced will be It will be red. We need the following ASP to combine all the previous things.
<%@ Language=VBScript %>
<%
Option Explicit
Dim oUser
Set oUser = NewCUser
If oUser.validate() Then
Set oUser = Nothing
Server.Transfer "NextPage.asp"
End If
%>
<html>
<body>
<form method="POST" action="GetUser.asp" name="thisForm" id="thisForm">
<%
Response.Write xslTransform(oUser.DOM, "user.xsl")
%>
<input type="hidden" name="txtUserXML" id="txtUserXML"
value="<%=oUser.DOM.xml%>">
<input type="submit" value="Submit">
</form>
</body>
</html>
<%
Set oUser = Nothing
Function xslTransform(vXML, XSLFileName)
Dim m_xml, m_xsl
If VarType(vXML) = 8 Then
Set m_xml = m_dom
m_xml.loadXML vXML
ElseIf VarType(vXML) = 9 Then
Set m_xml = vXML
End If
If m_xml.parseError.errorCode <> 0 Then _
Err.Raise vbObjectError, "XMLTransform(...)", m_xml.parseError.reason
Set m_xsl = Server.CreateObject("MSXML2.DOMDocument")
m_xsl.async = False
m_xsl.load Server.MapPath(XSLFileName)
If m_xsl.parseError.errorCode <> 0 Then _
Err.Raise vbObjectError, "XMLTransform(...)", m_xsl.parseError.reason
xslTransform = m_xml.transformNode(m_xsl)
Set m_xsl = Nothing
End Function
%>
<!--#include file="CUser.asp"-->
The ASP code creates the CUser object and fills in the data if there is data. The resulting HTML is then created via XSL transformation using CUser's DOM. The transformation is wrapped into a function called xslTransform. Also, remember to store the resulting CUser DOM into a hidden <INPUT> element. Or you can store the CUser DOM into a Session variable and get it out during initialization.
After completing this page, you can create other pages based on the previous skeleton code. Now you have created a copy-and-paste scenario for data collection. The most beautiful part of this solution is that all output is pure HTML, without any browser-specific properties or stylesheets. And because the functionality is wrapped into classes, you can use XSLT to generate layouts and the code runs pretty fast.
-------------------------------------------------- ----------------------------------
The author of this article: Phillip Perkins is a contractor of Ajilon Consulting. His experience ranges from machine control and client/server to intranet applications.