It is assumed that the reader has a good understanding of ASP, VBScript classes and XPath.
Hey, I wrote the "A Couple of ASP Functions for XML Data Transfer" functions and, as any self-respecting programmer, was unhappy with its stiffness. I decided enough is enough and created an actual class that handles more things. clsXML.asp is the actual class and objXML.asp is an implementation of the class. It can actually be used in a huge variety of ways. For example, if there is a need to store a recordset in XML, this class greatly aids in that process. It is very robust and allows for some pretty neat things.
Only one property: File. It needs to know where to look otherwise a new XML document must be created. In other words, if you try to get fields before specifying the document, it will not work.
Here are some of the methods included:
createFile - creates a new XML file by specifying the file name and the new root node
getField - returns all fields returned by an XPath query
updateField - updates all fields specified by an XPath query
createRootChild - can you guess?
createRootNodeWAttr - This function allows the creation of a root child with any attribute scheme imagined
createChildNode - This allows for a child node to be created under any node that is returned by an XPath query
createChildNodeWAttr - Ditto, but with the functionality of 5
deleteNode - Deletes any node that is returned by the XPath Query
A couple of errors you might encounter:
If the XML file is not well-formed, the XML object will not be created properly, also if the file does not exist (duh!).
When writing to a file, there might be a permissions error. Make sure that the directory which is being written to has all of the necessary permissions.
Happy programming!
File Listings
clsXML.asp
<%
Class clsXML
'strFile must be full path to document, ie C:\XML\XMLFile.XML
'objDoc is the XML Object
Private strFile, objDoc
'*********************************************************************
' Initialization/Termination
'*********************************************************************
'Initialize Class Members
Private Sub Class_Initialize()
strFile = ""
End Sub
'Terminate and unload all created objects
Private Sub Class_Terminate()
Set objDoc = NothingEnd Sub
'*********************************************************************
' Properties
'*********************************************************************
'Set XML File and objDoc
Public Property Let File(str)
Set objDoc = Server.CreateObject("Microsoft.XMLDOM")
objDoc.async = False
strFile = str
objDoc.Load strFile
End Property
'Get XML File
Public Property Get File()
File = strFile
End Property
'*********************************************************************
' Functions
'*********************************************************************
'Create Blank XML File, set current obj File to newly created file
Public Function createFile(strPath, strRoot)
Dim objFSO, objTextFile
Set objFSO = Server.CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.CreateTextFile(strPath, True)
objTextFile.WriteLine("<?xml version=""1.0""?>")
objTextFile.WriteLine("<" & strRoot & "/>")
objTextFile.Close
Me.File = strPath
Set objTextFile = NothingSet objFSO = NothingEnd Function
'Get XML Field(s) based on XPath input from root node
Public Function getField(strXPath)
Dim objNodeList, arrResponse(), i
Set objNodeList = objDoc.documentElement.selectNodes(strXPath)
ReDim arrResponse(objNodeList.length)
For i = 0 To objNodeList.length - 1
arrResponse(i) = objNodeList.item(i).Text
Next
getField = arrResponse
End Function
'Update existing node(s) based on XPath specs
Public Function updateField(strXPath, strData)
Dim objField
For Each objField In objDoc.documentElement.selectNodes(strXPath)
objField.Text = strData
Next
objDoc.Save strFile
Set objField = Nothing
updateField = TrueEnd Function
'Create node directly under root
Public Function createRootChild(strNode)
Dim objChild
Set objChild = objDoc.createNode(1, strNode, "")
objDoc.documentElement.appendChild(objChild)
objDoc.Save strFile
Set objChild = NothingEnd Function
'Create a child node under root node with attributes
Public Function createRootNodeWAttr(strNode, attr, val)
Dim objChild, objAttr
Set objChild = objDoc.createNode(1, strNode, "")
If IsArray(attr) And IsArray(val) ThenIf UBound(attr)-LBound(attr) <> UBound(val)-LBound(val) ThenExit FunctionElseDim i
For i = LBound(attr) To UBound(attr)
Set objAttr = objDoc.createAttribute(attr(i))
objChild.setAttribute attr(i), val(i)
Next
End If
ElseSet objAttr = objDoc.createAttribute(attr)
objChild.setAttribute attr, val
End If
objDoc.documentElement.appendChild(objChild)
objDoc.Save strFile
Set objChild = NothingEnd Function
'Create a child node under the specified XPath Node
Public Function createChildNode(strXPath, strNode)
Dim objParent, objChild
For Each objParent In objDoc.documentElement.selectNodes(strXPath)
Set objChild = objDoc.createNode(1, strNode, "")
objParent.appendChild(objChild)
Next
objDoc.Save strFile
Set objParent = NothingSet objChild = NothingEnd Function
'Create a child node(s) under the specified XPath Node with attributes
Public Function createChildNodeWAttr(strXPath, strNode, attr, val)
Dim objParent, objChild, objAttr
For Each objParent In objDoc.documentElement.selectNodes(strXPath)
Set objChild = objDoc.createNode(1, strNode, "")
If IsArray(attr) And IsArray(val) ThenIf UBound(attr)-LBound(attr) <> UBound(val)-LBound(val) ThenExit Function
ElseDim i
For i = LBound(attr) To UBound(attr)
Set objAttr = objDoc.createAttribute(attr(i))
objChild.SetAttribute attr(i), val(i)
Next
End If
ElseSet objAttr = objDoc.createAttribute(attr)
objChild.setAttribute attr, val
End If
objParent.appendChild(objChild)
Next
objDoc.Save strFile
Set objParent = NothingSet objChild = NothingEnd Function
'Delete the node specified by the XPath
Public Function deleteNode(strXPath)
Dim objOld
For Each objOld In objDoc.documentElement.selectNodes(strXPath)
objDoc.documentElement.removeChild objOld
Next
objDoc.Save strFile
Set objOld = NothingEnd FunctionEnd Class
%>
This implementation of the class creates a new XML document. If you simply want to use an existing XML document, simply call the File property and specify the path.
objXML.asp
<%@ Language=VBScript %>
<% Option Explicit %>
<!--#INCLUDE FILE="clsXML.asp"-->
<%
Dim objXML, strPath, str
Set objXML = New clsXML
strPath = Server.MapPath(".") & "\New.xml"
objXML.createFile strPath, "Root"
'Or If using an existing XML file:
'objXML.File = "C:\File.xml"
objXML.createRootChild "Images"
'Here only one attribute is added to the Images/Image Node
objXML.createChildNodeWAttr "Images", "Image", "id", "1"
objXML.updateField "Images//Image[@id=1]", "super.gif"
objXML.createRootNodeWAttr "Jobs", Array("Size", "Length", "Width"), _
Array(24, 31, 30)
objXML.createRootNodeWAttr "Jobs", Array("Size", "Length", "Width"), _
Array(24, 30, 29)
objXML.createRootNodeWAttr "Jobs", Array("Size", "Length", "Width"), _
Array(24, 31, 85)
'Notice that all three job nodes have size 24, all of those
'nodes will be updated
objXML.updateField "Jobs[@Size=24]", "24's"
'Notice that only two nodes have the specified XPath, hence
'only two new child nodes will be added
objXML.createChildNodeWAttr "Jobs[@Size=24 and @Length=31]", "Specs", _
Array("Wood", "Metal", "Color"), _
Array("Cedar", "Aluminum", "Green")
'It is always important to iterate through all of the nodes
'returned by this XPath query.
For Each str In objXML.getField("Jobs[@Size=24]")
Response.Write(str & "<br>")
NextSet objXML = Nothing
Response.Redirect "New.xml"
%>