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
<% 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 = Nothing End 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 = Nothing Set objFSO = Nothing End 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 = True End 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 = Nothing End 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) Then If UBound(attr)-LBound(attr) <> UBound(val)-LBound(val) Then Exit Function Else Dim i For i = LBound(attr) To UBound(attr) Set objAttr = objDoc.createAttribute(attr(i)) objChild.setAttribute attr(i), val(i) Next End If Else Set objAttr = objDoc.createAttribute(attr) objChild.setAttribute attr, val End If objDoc.documentElement.appendChild(objChild) objDoc.Save strFile Set objChild = Nothing End 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 = Nothing Set objChild = Nothing End 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) Then If UBound(attr)-LBound(attr) <> UBound(val)-LBound(val) Then Exit Function Else Dim i For i = LBound(attr) To UBound(attr) Set objAttr = objDoc.createAttribute(attr(i)) objChild.SetAttribute attr(i), val(i) Next End If Else Set objAttr = objDoc.createAttribute(attr) objChild.setAttribute attr, val End If objParent.appendChild(objChild) Next objDoc.Save strFile Set objParent = Nothing Set objChild = Nothing End 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 = Nothing End Function End 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.
<%@ 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>") Next Set objXML = Nothing Response.Redirect "New.xml" %> |
Here is the output of the implementation:
<?xml version="1.0"?> <Root> <Images> <Image id="1">super.gif</Image> </Images> <Jobs Size="24" Length="31" Width="30"> 24's <Specs Wood="Cedar" Metal="Aluminum" Color="Green"/> </Jobs> <Jobs Size="24" Length="30" Width="29"> 24's </Jobs> <Jobs Size="24" Length="31" Width="85"> 24's <Specs Wood="Cedar" Metal="Aluminum" Color="Green"/> </Jobs> </Root> |
Questions? Email me!
In part 2 we’ll look at the .NET implementation of the exact same thing.
Seth Juarez
Technology Consultant
Holman’s of Nevada Inc.
e-mail: [email protected]
Download
You can download all the files listed above in this one zip file.