卜酷塔 发表于 2005-5-19 16:38

[转帖]使用纯HTML的通用数据管理和服务

<FONT><FONT size=3> </FONT>
<P>使用纯HTML的通用数据管理和服务。然而,为了收集数据,你需要一个数据储存库。要避免使用数据库服务器带来的很多问题,你可以在XML中收集这些数据。下面是我们的项目的基本结构:

&lt;user&gt;
    &lt;first_name/&gt;
    &lt;last_name/&gt;
    &lt;mi/&gt;
&lt;/user&gt;</P>
<P>我最初将数据限制为first name,last name和middle。这个页面之后的基本思想是用户信息在这个页面中获得。在用户信息需求得到满足以后,流程必须被转到下一个逻辑收集步骤。为了使事情变得简单,我将把用户功能包装到一个ASP类中。</P>
<P>Function Coalesce(vVar, vAlt)
    If vVal = "" Or VarType(vVal) = 1 Or VarType(vVal) = 0 Then
        Coalesce = vAlt
    Else
        Coalesce = vVal
    End If
End Function</P>
<P>Class CUser
Private m_SQL, m_DOM</P>
<P>Public Property Get DOM()
    Set DOM = m_DOM
End Property</P>
<P>Public Sub saveUser()
    m_SQL.save "save_user", m_DOM
End Sub</P>
<P>Public Function validate()
    m_DOM.loadXML "&lt;root&gt;" &amp; m_SQL.validateUser(m_DOM) &amp; "&lt;/root&gt;"
    If Not m_DOM.selectSingleNode("//error") Is Nothing Then
        validate = False
    Else
        validate = True
    End If
End Function</P>
<P>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("//" &amp; sKey &amp; "s")
        If Not parent_node Is Nothing Then
            For n = 1 To oCollection(sKey).Count
                Set node = parent_node.selectSingleNode(sKey &amp; _
                                                        "[string(.)='" &amp;
oCollection(sKey)(n) &amp; "']")
                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("//" &amp; sKey)
            If Not node Is Nothing Then _
                node.text = Coalesce(oCollection(sKey), "")
        End If
    Next
End Sub</P>
<P>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 "&lt;root&gt;" &amp; Server.MapPath("user.xml") &amp; "&lt;/root&gt;"
    End If
    collectData m_DOM, Request.Form
    collectData m_DOM, Request.QueryString
End Sub</P>
<P>Private Sub Class_Terminate()
    Set m_SQL = Nothing
    Set m_DOM = Nothing
End Sub</P>
<P>End Class</P>
<P>Class CSQL
Private m_DAL, m_Stream</P>
<P>Public Function save(sStoredProc, oDOM)
    'adVarChar = 200
    m_DAL.RunSP Array(m_DAL.mp("@xml_param", 200, 8000, oDOM.xml))
End Function</P>
<P>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</P>
<P>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</P>
<P>Private Sub Class_Terminate()
    Set m_DAL = Nothing
    Set m_Stream = Nothing
End Sub</P>
<P>End Class
CSQL类是基于一个数据访问层(m_DAL)组件MyPkg.MyDAL建立起来的。而这个组件则是基于Fitch和Mather DAL组件建立起来的,这两个组件可以从MSDN找到。这样我们就在SQL Server与你的代码建立了桥梁。</P>
<P>
当CUser对象初始化之后,它收集Request数据并使用collectData()子函数将收集到的数据放到UserDOM的一个相应的节点中。(代码我不再解释,因为它本身相当容易理解。)在收集了数据之后(或者不收集数据),我们将使用XSL将数据内容转变成布局。</P>
<P>&lt;?xml version="1.0"?&gt;
&lt;xsl:stylesheet xmlns:xsl=http://www.w3.org/1999/XSL/Transform
    version="1.0"&gt;
&lt;xsl:output method="html"/&gt;</P>
<P>&lt;xsl:template match="/"&gt;
    &lt;xsl:if test="//error"&gt;
    &lt;font color="red"&gt;*Information in red is required&lt;br/&gt;&lt;/font&gt;
    &lt;/xsl:if&gt;
    &lt;xsl:apply-templates select="//user"/&gt;
&lt;/xsl:template&gt;</P>
<P>&lt;xsl:template match="user"&gt;
    &lt;font&gt;
        &lt;xsl:attribute name="color"&gt;
            &lt;xsl:choose&gt;
                &lt;xsl:when test="//error[.='first name']"&gt;red&lt;/xsl:when&gt;
                &lt;xsl:otherwise&gt;black&lt;/xsl:otherwise&gt;
            &lt;/xsl:choose&gt;
        &lt;/xsl:attribute&gt;
    First Name:
    &lt;/font&gt;
    &lt;input type="text" name="first_name"&gt;
        &lt;xsl:attribute name="value"&gt;&lt;xsl:value-of
select="first_name"/&gt;&lt;/xsl:attribute&gt;
    &lt;/input&gt;&lt;br/&gt;
    &lt;font&gt;
        &lt;xsl:attribute name="color"&gt;
            &lt;xsl:choose&gt;
                &lt;xsl:when test="//error[.='mi']"&gt;red&lt;/xsl:when&gt;
                &lt;xsl:otherwise&gt;black&lt;/xsl:otherwise&gt;
            &lt;/xsl:choose&gt;
        &lt;/xsl:attribute&gt;
    MI:
    &lt;/font&gt;
    &lt;input type="text" name="mi"&gt;
        &lt;xsl:attribute name="value"&gt;&lt;xsl:value-of select="mi"/&gt;&lt;/xsl:attribute&gt;
    &lt;/input&gt;&lt;br/&gt;
    &lt;font&gt;
        &lt;xsl:attribute name="color"&gt;
            &lt;xsl:choose&gt;
                &lt;xsl:when test="//error[.='last_name']"&gt;red&lt;/xsl:when&gt;
                &lt;xsl:otherwise&gt;black&lt;/xsl:otherwise&gt;
            &lt;/xsl:choose&gt;
        &lt;/xsl:attribute&gt;
    Last Name:
    &lt;/font&gt;
    &lt;input type="text" name="last_name"&gt;
        &lt;xsl:attribute name="value"&gt;&lt;xsl:value-of
select="last_name"/&gt;&lt;/xsl:attribute&gt;
    &lt;/input&gt;&lt;br/&gt;
&lt;/xsl:template&gt;</P>
<P>&lt;/xsl:stylesheet&gt; </P>
<P>这个样式表将把内容转成布局。错误检查是很重要的,存储过程通过确定数据是否需要处理来检查数据。对于不能为空但又没有填充数据的每个域返回一个“errors”节点。这个XML的输出大致如下:</P>
<P>    &lt;user&gt;. . .&lt;/user&gt;&lt;errors&gt;&lt;error&gt;first_name&lt;/error&gt;. . .&lt;/errors&gt;
这个样式表将把内容转成布局。错误检查是很重要的,存储过程通过确定数据是否需要处理来检查数据。对于不能为空但又没有填充数据的每个域返回一个“errors”节点。这个XML的输出大致如下:</P>
<P>    &lt;user&gt;. . .&lt;/user&gt;&lt;errors&gt;&lt;error&gt;first_name&lt;/error&gt;. . .&lt;/errors&gt; </P>
<P>注意如果有一个错误匹配了节点名,那么产生的输出将会是红色的。我们需要下面的一个ASP将前面的所有东西组合起来。</P>
<P>&lt;%@ Language=VBScript %&gt;
&lt;%
Option Explicit
Dim oUser
Set oUser = New CUser
If oUser.validate() Then
    Set oUser = Nothing
    Server.Transfer "NextPage.asp"
End If
%&gt;
&lt;html&gt;
&lt;body&gt;
&lt;form method="POST" action="GetUser.asp" name="thisForm" id="thisForm"&gt;
&lt;%
Response.Write xslTransform(oUser.DOM, "user.xsl")
%&gt;
&lt;input type="hidden" name="txtUserXML" id="txtUserXML"
value="&lt;%=oUser.DOM.xml%&gt;"&gt;
&lt;input type="submit" value="Submit"&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
&lt;%
Set oUser = Nothing</P>
<P>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 &lt;&gt; 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 &lt;&gt; 0 Then _
        Err.Raise vbObjectError, "XMLTransform(...)", m_xsl.parseError.reason
    xslTransform = m_xml.transformNode(m_xsl)
    Set m_xsl = Nothing
End Function
%&gt;
&lt;!--#include file="CUser.asp"--&gt; </P>
<P>ASP代码创建CUser对象,如果有数据就填充数据。然后使用CUser的DOM通过XSL转换来创建结果HTML。转换被包装到一个叫做xslTransform的函数之中。而且,记住要将结果CUser DOM存储到一个隐藏的&lt;INPUT&gt;元素中。或者你可以将CUser DOM存储到一个Session变量中并在初始化过程中将其取出。</P>
<P>在完成这个页面之后,你可以基于前面的骨架代码创建其它的页面。现在你已经创建了一个数据收集的拷贝-粘贴方案。这个方案最优美的部分在于所有的输出都是纯HTML,没有任何浏览器特有的性质或者样式表。而且由于功能都被包装到类中,所以你可以使用XSLT产生布局,代码运行相当快。</P></FONT>


页: [1]

编程论坛