使用純HTML的通用數(shù)據(jù)管理和服務(wù)。然而,為了收集數(shù)據(jù),你需要一個(gè)數(shù)據(jù)儲(chǔ)存庫(kù)。要避免使用數(shù)據(jù)庫(kù)服務(wù)器帶來(lái)的很多問(wèn)題,你可以在XML中收集這些數(shù)據(jù)。下面是我們的項(xiàng)目的基本結(jié)構(gòu):
user>
first_name/>
last_name/>
mi/>
/user>
我最初將數(shù)據(jù)限制為first name,last name和middle。這個(gè)頁(yè)面之后的基本思想是用戶信息在這個(gè)頁(yè)面中獲得。在用戶信息需求得到滿足以后,流程必須被轉(zhuǎn)到下一個(gè)邏輯收集步驟。為了使事情變得簡(jiǎn)單,我將把用戶功能包裝到一個(gè)ASP類中。
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("http://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("http://" 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("http://" 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
CSQL類是基于一個(gè)數(shù)據(jù)訪問(wèn)層(m_DAL)組件MyPkg.MyDAL建立起來(lái)的。而這個(gè)組件則是基于Fitch和Mather DAL組件建立起來(lái)的,這兩個(gè)組件可以從MSDN找到。這樣我們就在SQL Server與你的代碼建立了橋梁。
當(dāng)CUser對(duì)象初始化之后,它收集Request數(shù)據(jù)并使用collectData()子函數(shù)將收集到的數(shù)據(jù)放到UserDOM的一個(gè)相應(yīng)的節(jié)點(diǎn)中。(代碼我不再解釋,因?yàn)樗旧硐喈?dāng)容易理解。)在收集了數(shù)據(jù)之后(或者不收集數(shù)據(jù)),我們將使用XSL將數(shù)據(jù)內(nèi)容轉(zhuǎn)變成布局。
?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="http://error">
font color="red">*Information in red is requiredbr/>/font>
/xsl:if>
xsl:apply-templates select="http://user"/>
/xsl:template>
xsl:template match="user">
font>
xsl:attribute name="color">
xsl:choose>
xsl:when test="http://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="http://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="http://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>
這個(gè)樣式表將把內(nèi)容轉(zhuǎn)成布局。錯(cuò)誤檢查是很重要的,存儲(chǔ)過(guò)程通過(guò)確定數(shù)據(jù)是否需要處理來(lái)檢查數(shù)據(jù)。對(duì)于不能為空但又沒(méi)有填充數(shù)據(jù)的每個(gè)域返回一個(gè)“errors”節(jié)點(diǎn)。這個(gè)XML的輸出大致如下:
user>. . ./user>errors>error>first_name/error>. . ./errors>
這個(gè)樣式表將把內(nèi)容轉(zhuǎn)成布局。錯(cuò)誤檢查是很重要的,存儲(chǔ)過(guò)程通過(guò)確定數(shù)據(jù)是否需要處理來(lái)檢查數(shù)據(jù)。對(duì)于不能為空但又沒(méi)有填充數(shù)據(jù)的每個(gè)域返回一個(gè)“errors”節(jié)點(diǎn)。這個(gè)XML的輸出大致如下:
user>. . ./user>errors>error>first_name/error>. . ./errors>
注意如果有一個(gè)錯(cuò)誤匹配了節(jié)點(diǎn)名,那么產(chǎn)生的輸出將會(huì)是紅色的。我們需要下面的一個(gè)ASP將前面的所有東西組合起來(lái)。
%@ Language=VBScript %>
%
Option Explicit
Dim oUser
Set oUser = New CUser
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"-->
ASP代碼創(chuàng)建CUser對(duì)象,如果有數(shù)據(jù)就填充數(shù)據(jù)。然后使用CUser的DOM通過(guò)XSL轉(zhuǎn)換來(lái)創(chuàng)建結(jié)果HTML。轉(zhuǎn)換被包裝到一個(gè)叫做xslTransform的函數(shù)之中。而且,記住要將結(jié)果CUser DOM存儲(chǔ)到一個(gè)隱藏的INPUT>元素中?;蛘吣憧梢詫User DOM存儲(chǔ)到一個(gè)Session變量中并在初始化過(guò)程中將其取出。
在完成這個(gè)頁(yè)面之后,你可以基于前面的骨架代碼創(chuàng)建其它的頁(yè)面?,F(xiàn)在你已經(jīng)創(chuàng)建了一個(gè)數(shù)據(jù)收集的拷貝-粘貼方案。這個(gè)方案最優(yōu)美的部分在于所有的輸出都是純HTML,沒(méi)有任何瀏覽器特有的性質(zhì)或者樣式表。而且由于功能都被包裝到類中,所以你可以使用XSLT產(chǎn)生布局,代碼運(yùn)行相當(dāng)快。
--------------------------------------------------------------------------------
本文作者:Phillip Perkins是Ajilon Consulting的簽約人。他的經(jīng)驗(yàn)很豐富,從機(jī)器控制和客戶/服務(wù)器到企業(yè)內(nèi)部網(wǎng)應(yīng)用。