%
Class XmlForm
Private m_Doc
Private m_IsValid
Private m_FileName
Private m_Log
Public Sub Class_Initialize()
Set m_Doc = CreateObject("MSXML2.DOMDocument.4.0")
Set m_Log = New Logger : m_Log.Level = "ERROR" : m_Log.BufferOutput = True : m_Log.Name = "XmlForm"
m_IsValid = True
End Sub
' Loads the definition from an XML file.
Public Function Load(FileName)
m_FileName = Server.MapPath(FileName)
Load = m_Doc.Load(m_FileName)
If Not Load Then
Dim Error : Set Error = m_Doc.parseError
m_Log.Error "Xml parsing error at line " & Error.Line _
& ", char " & Error.LinePos & ": " & Error.Reason _
& " " & Error.SrcText
End If
End Function
' Loads the definition from a string.
Public Function LoadXml(XmlString)
LoadXml = m_Doc.LoadXml(XmlString)
If Not LoadXml Then
Dim Error : Set Error = m_Doc.parseError
m_Log.Error "Xml parsing error at line " & Error.Line _
& ", char " & Error.LinePos & ": " & Error.Reason _
& " " & Error.SrcText
End If
End Function
' Returns whether the form is valid or not.
Public Property Get IsValid
IsValid = m_IsValid
End Property
' Returns text that you can insert into a web page to display the form.
Public Function ToString()
Dim NewDoc, Hidden, Node, FormNode, Action
' If the form hasn't got an action, set the action to the current page.
Set FormNode = m_Doc.selectSingleNode("/form")
If FormNode.getAttribute("action") = "" Or IsNull(FormNode.getAttribute("action")) Then
Action = Request.ServerVariables("URL")
If FormNode.getAttribute("method") = "POST" Then
Action = Action & "?" & Request.QueryString
End If
FormNode.setAttribute "action", Action
End If
' Clone the document so we can remove elements that should be hidden,
' without modifying the original document
Set NewDoc = m_Doc.cloneNode(True)
Set Hidden = NewDoc.selectNodes("//node()[@hidden='1']")
For Each Node In Hidden
Node.parentNode.removeChild Node
Next
ToString = NewDoc.Xml
End Function
' Populates the form with data submitted by the browser.
Public Sub Grab()
Dim Config, Form, Method
' Get the element that describes the form, and the form itself.
Set Config = m_Doc.selectSingleNode("/form/config")
Set Form = m_Doc.selectSingleNode("/form")
If Form Is Nothing Or Config Is Nothing Then
m_IsValid = False
Else
Method = Form.getAttribute("method")
' See if the browser posted any form data. If not, then there is no
' point trying to set element values.
If GetBrowserData(Method, "formSanityCheck") = "" Then
m_IsValid = False
Else
' For each element described in the config element, get the element or
' list of elements in the form, and populate them with the browser's
' data.
Dim Node
For Each Node In m_Doc.DocumentElement.selectNodes("/form/config/element")
SetValue Node.getAttribute("name"), GetBrowserData(Method, Node.getAttribute("name"))
Next
End If
End If
End Sub
' Gets a value from the form, by name
Public Function GetValue(Name)
Dim Config, Node, Val, Options, Child, Result(), i
Set Config = m_Doc.selectSingleNode("/form/config/element[@name='" & Name & "']")
If Config Is Nothing Then
m_Log.Error "The form element '" & Name & "' is not defined in the config."
Exit Function
End If
' Get the element's value
If Config.getAttribute("type") = "array" Then
If Config.getAttribute("tag-name") = "input" Then ' It's a CheckBox
Set Options = m_Doc.selectNodes("//input[@type='checkbox' and @checked='1' and @name='" & Name & "']")
ReDim Result(Options.Length - 1)
For i = 0 To Options.Length - 1
Result(i) = Options(i).Attributes.getNamedItem("value").Text
Next
GetValue = Result
ElseIf Config.getAttribute("tag-name") = "select" Then
Set Node = m_Doc.selectSingleNode("//select[@id='" & Config.getAttribute("element-id") & "']")
Set Options = Node.selectNodes("option[@selected='1']")
ReDim Result(Options.Length - 1)
For i = 0 To Options.Length - 1
Result(i) = Options(i).Attributes.getNamedItem("value").Text
Next
GetValue = Result
End If
ElseIf Config.getAttribute("element-id") <> "" Then
' It's a scalar that's not a radio button or checkbox array
Set Node = m_Doc.selectSingleNode("//node()[@id='" & Config.getAttribute("element-id") & "']")
If Not Node Is Nothing Then
If Node.nodeName = "select" Then
' Find the correct child node of the element and get its value
For Each Child In Node.selectNodes("option")
If Child.getAttribute("selected") <> "" Then
GetValue = Child.getAttribute("value")
End If
Next
ElseIf Node.nodeName = "input" Then
' It's a TextBox, Password, Hidden, Button, Submit, or Reset
Select Case Node.getAttribute("type")
Case "checkbox"
If Not IsNull(Node.getAttribute("checked")) And Not IsNull(Node.getAttribute("value")) Then
If Node.getAttribute("checked") = "1" Then
GetValue = Node.getAttribute("value")
Else
GetValue = ""
End If
End If
Case Else
If Not IsNull(Node.getAttribute("value")) Then
GetValue = Node.getAttribute("value")
Else
GetValue = ""
End If
End Select
Else ' Textarea
GetValue = Node.Text
End If
End If
Else
' It's a scalar that's a radio button, or *scalar* checkbox array
Set Options = m_Doc.selectNodes("//input[@name='" & Name & "' and @checked='1']")
If Options.Length > 0 Then
GetValue = Options(0).Attributes.getNamedItem("value").Text
End If
End If
If IsArray(GetValue) Then
m_Log.Debug "Got value for " & Name & ". Result: ('" & Join(GetValue, "', '") & "')"
Else
m_Log.Debug "Got value for " & Name & ". Result: " & GetValue
End If
End Function
' Sets the value of a form element
Public Sub SetValue(Name, Value)
Dim Config, Node, Checkboxes, Child, OneVal, Radios, Options
' If the value isn't a string, stringify it
If Not IsArray(Value) Then
Value = CStr(Value)
End If
' If the element isn't defined in the config, quit
Set Config = m_Doc.selectSingleNode("/form/config/element[@name='" & Name & "']")
If Not Config Is Nothing Then
' There are two types of form elements: arrays and scalars.
If Config.getAttribute("type") = "array" Then
' An array means that there could be multiple values submitted
' for this element. Form elements that are arrays by nature
' are
' * CheckBox
' * SelectMultiple
' First array-ize the value
If Not IsArray(Value) Then
Value = Array(Value)
End If
' Find out what kind of form element it is
If Config.getAttribute("tag-name") = "input" Then
' It's a CheckBox array. Uncheck everything there's no data for, and
' check everything there is
Set Checkboxes = m_Doc.selectNodes("//input[@name='" & Name & "' and @type='checkbox']")
For Each Child In Checkboxes
If InArray(Value, Child.getAttribute("value")) Then
Child.SetAttribute ("checked"), 1
Else
Child.RemoveAttribute ("checked")
End If
Next
Else
' It's a