Chapter 10 (Performance and XML) Samples
Listing 10.1. Using the XML DOM to Save and Load Data from a File
Option Strict On Option Compare Binary Imports System '----------------------------------------------- 'Shows saving and loading data imports the 'XML Document Object Model '----------------------------------------------- Public Class SaveAndLoadXML_UseDOM 'XML Tags we will use in our document Const XML_ROOT_TAG As String = "AllMyData" Const XML_USERINFO_TAG As String = "UserInfo" Const XML_USERID_TAG As String = "UserID" Const XML_NAMEINFO_TAG As String = "Name" Const XML_FIRSTNAME_TAG As String = "FirstName" Const XML_LASTNAME_TAG As String = "LastName" '---------------------------------------------------------- 'Loads the state of the user ' ' [in] fileName: The name of the file we are saving to ' [out] userId: UserID we have loaded ' [out] firstName: User's FirstName we have loaded ' [out] lastName:User's LastName we have loaded '---------------------------------------------------------- Public Shared Sub XML_LoadUserInfo(ByVal fileName As String, _ ByRef userId As Integer, ByRef firstName As String, _ ByRef lastName As String) 'Start out with null values userId = 0 firstName = " lastName = " 'Assume we have not loaded the user data Dim gotUserInfoData As Boolean = False Dim xmlDocument As System.Xml.XmlDocument = _ New System.Xml.XmlDocument xmlDocument.Load(fileName) 'Grab the root node Dim rootElement As System.Xml.XmlElement rootElement = _ CType(xmlDocument.ChildNodes(0), System.Xml.XmlElement) 'Make sure the root node matches our expected text 'Otherwise, this could just be some random other XML file If (rootElement.Name <> XML_ROOT_TAG) Then Throw New Exception("Root node not of expected type!") End If '----------------------------------------- 'A simple machine that iterates through all the nodes '----------------------------------------- Dim childOf_RootNode As System.Xml.XmlElement For Each childOf_RootNode In _ rootElement.ChildNodes 'If it's a UserInfo node, we want to look inside it If (childOf_RootNode.Name = XML_USERINFO_TAG) Then gotUserInfoData = True 'We found the user data '-------------------------------------- 'Load each of the subitems '-------------------------------------- Dim child_UserDataNode As System.Xml.XmlElement For Each child_UserDataNode In _ childOf_RootNode.ChildNodes 'UserID If (child_UserDataNode.Name = XML_USERID_TAG) Then userId = CInt(child_UserDataNode.InnerText) 'UserName ElseIf (child_UserDataNode.Name = XML_NAMEINFO_TAG) Then Dim child_Name As System.Xml.XmlElement For Each child_Name In child_UserDataNode.ChildNodes 'FirstName If (child_Name.Name = XML_FIRSTNAME_TAG) Then firstName = child_Name.InnerText 'LastName ElseIf (child_Name.Name = XML_LASTNAME_TAG) Then lastName = child_Name.InnerText End If Next 'End of UserName parsing loop End If '"End if" for "is UserName?" Next 'End of UserInfo parsing loop End If '"End if" for "is UserInfo"? Next 'End of root node parsing loop If (gotUserInfoData = False) Then Throw New Exception("User data not found in XML!") End If End Sub '----------------------------------------------------------- 'Saves the state of the user ' ' [in] fileName: The name of the file we are saving to ' [in] userId: UserID we want to save ' [in] firstName: User's FirstName we want to save ' [in] lastName: User's LastName we want to save '----------------------------------------------------------- Public Shared Sub XML_SaveUserInfo(ByVal fileName As String, _ ByVal userId As Integer, ByVal firstName As String, _ ByVal lastName As String) Dim xmlDocument As System.Xml.XmlDocument = _ New System.Xml.XmlDocument '--------------------------------------------------------- 'Add the top-level document element '--------------------------------------------------------- Dim rootNodeForDocument As System.Xml.XmlElement rootNodeForDocument = xmlDocument.CreateElement( _ XML_ROOT_TAG) xmlDocument.AppendChild(rootNodeForDocument) '--------------------------------------------------------- 'Add the data for the user info '--------------------------------------------------------- Dim topNodeForUserData As System.Xml.XmlElement topNodeForUserData = xmlDocument.CreateElement( _ XML_USERINFO_TAG) rootNodeForDocument.AppendChild(topNodeForUserData) '--------------------------------------------------------- 'Add the UserID value to our document '--------------------------------------------------------- 'Create a subnode for the namespace info Dim subNodeForUserID As System.Xml.XmlElement subNodeForUserID = _ xmlDocument.CreateElement(XML_USERID_TAG) subNodeForUserID.InnerText = _ System.Convert.ToString(userId) 'Attach the UserID subnode to the top-level node topNodeForUserData.AppendChild(subNodeForUserID) '--------------------------------------------------------- 'Add all the NameInfo values to our document '--------------------------------------------------------- 'Create a subnode for the namespace info Dim subNodeForNameInfo As System.Xml.XmlElement subNodeForNameInfo = xmlDocument.CreateElement( _ XML_NAMEINFO_TAG) 'FirstName Dim subNodeFirstName As System.Xml.XmlElement subNodeFirstName = xmlDocument.CreateElement( _ XML_FIRSTNAME_TAG) subNodeFirstName.InnerText = firstName 'LastName Dim subNodeLastName As System.Xml.XmlElement subNodeLastName = xmlDocument.CreateElement( _ XML_LASTNAME_TAG) subNodeLastName.InnerText = lastName 'Attach the first And last name subnodes to the NameInfo 'parent note subNodeForNameInfo.AppendChild(subNodeFirstName) subNodeForNameInfo.AppendChild(subNodeLastName) 'Attach the NameInfo subnode (with its children too) to 'the top-level node topNodeForUserData.AppendChild(subNodeForNameInfo) '--------------------------------------------------------- 'Save the document '--------------------------------------------------------- Try xmlDocument.Save(fileName) Catch ex As System.Exception MsgBox( _ "Error occurred saving XML document - " + ex.Message) End Try End Sub 'End of function End Class 'End of class
Listing 10.2. Calling the XML Save and Load Code
Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Const FILENAME As String = "TestFileName.XML" 'Save imports the XML DOM SaveAndLoadXML_UseDOM.XML_SaveUserInfo(FILENAME, 14, "Ivo", _ "Salmre") 'Save imports the forward only XMLWriter 'SaveAndLoadXML_UseReaderWriter.XML_SaveUserInfo(FILENAME, _ ' 18, "Ivo", "Salmre") Dim userID As Integer Dim firstName As String Dim lastName As String 'Load imports the XML DOM SaveAndLoadXML_UseDOM.XML_LoadUserInfo(FILENAME, userID, _ firstName, lastName) 'Load imports the forward only XML Reader 'SaveAndLoadXML_UseReaderWriter.XML_LoadUserInfo(FILENAME, _ ' userID, firstName, lastName) MsgBox("Done! " + _ userID.ToString() + ", " + lastName + ", " + firstName) End Sub
Listing 10.3. Using the Forward-Only XML Reader/Writers to Save and Load XML Data from a File
Option Strict On Option Compare Binary Imports System Public Class SaveAndLoadXML_UseReaderWriter 'XML Tags we will use in our document Const XML_ROOT_TAG As String = "AllMyData" Const XML_USERINFO_TAG As String = "UserInfo" Const XML_USERID_TAG As String = "UserID" Const XML_NAMEINFO_TAG As String = "Name" Const XML_FIRSTNAME_TAG As String = "FirstName" Const XML_LASTNAME_TAG As String = "LastName" 'The set of states we are tracking as we read in data Private Enum ReadLocation inAllMyData inUserInfo inUserID inName inFirstName inLastName End Enum '----------------------------------------------------------- 'Saves the state of the user ' ' (in) fileName: The name of the file we are saving to ' (in) userId: UserID we have loaded ' (in) firstName: User's FirstName we have loaded ' (in) lastName: User's LastName we have loaded '----------------------------------------------------------- Public Shared Sub XML_SaveUserInfo(ByVal fileName As String, _ ByVal userId As Integer, ByVal firstName As String, _ ByVal lastName As String) Dim xmlTextWriter As System.Xml.XmlTextWriter xmlTextWriter = New System.Xml.XmlTextWriter(fileName, _ System.Text.Encoding.Default) 'Write out the contents of the document! '<Root> xmlTextWriter.WriteStartElement(XML_ROOT_TAG) '<Root> xmlTextWriter.WriteStartElement(XML_USERINFO_TAG) '<Root><UserID> '<Root><UserInfo> xmlTextWriter.WriteStartElement(XML_NAMEINFO_TAG) '<Root><UserInfo><Name> xmlTextWriter.WriteStartElement(XML_FIRSTNAME_TAG) '<Root><UserInfo><Name><FirstName> xmlTextWriter.WriteString(firstName) 'Value being written xmlTextWriter.WriteEndElement() 'Close first name '<Root><UserInfo><Name> xmlTextWriter.WriteStartElement(XML_LASTNAME_TAG) '<Root><UserInfo><Name><LastName> xmlTextWriter.WriteString(lastName) 'Value being written xmlTextWriter.WriteEndElement() 'Close last name '<Root><UserInfo><Name> xmlTextWriter.WriteEndElement() 'Close Name '<Root><UserInfo> '<Root><UserInfo> xmlTextWriter.WriteStartElement(XML_USERID_TAG) '<Root><UserInfo><UserID> 'Value being written xmlTextWriter.WriteString(userId.ToString()) xmlTextWriter.WriteEndElement() 'Close UserID '<Root><UserInfo> xmlTextWriter.WriteEndElement() 'Close UserInfo '<Root> xmlTextWriter.WriteEndElement() 'Close Document xmlTextWriter.Close() End Sub '---------------------------------------------------------- 'Loads the state of the user ' ' (in) fileName: The name of the file we are saving to ' (out) userId: UserID we have loaded ' (out) firstName: User's FirstName we have loaded ' (out) lastName: User's LastName we have loaded '---------------------------------------------------------- Public Shared Sub XML_LoadUserInfo(ByVal fileName As String, _ ByRef userId As Integer, ByRef firstName As String, _ ByRef lastName As String) Dim currentReadLocation As ReadLocation 'Start out with null values userId = 0 firstName = " lastName = " Dim xmlReader As System.Xml.XmlTextReader = _ New System.Xml.XmlTextReader(fileName) xmlReader.WhitespaceHandling = _ System.Xml.WhitespaceHandling.None Dim readSuccess As Boolean readSuccess = xmlReader.Read() If (readSuccess = False) Then Throw New System.Exception("No XML data to read!") End If 'Make sure we recognize the root tag. If (xmlReader.Name <> XML_ROOT_TAG) Then Throw New System.Exception( _ "Root tag different from expected!") End If 'Note where we are in the document currentReadLocation = ReadLocation.inAllMyData '----------------------------------------------- 'Loop through our document and read what we need '----------------------------------------------- While (readSuccess) Select Case (xmlReader.NodeType) 'Called when we enter a new element Case System.Xml.XmlNodeType.Element Dim nodeName As String = xmlReader.Name LoadHelper_NewElementEncountered(nodeName, _ currentReadLocation) '-------------------------------------------------- 'Here's where we can actually extract some text and 'get the data we are trying to load '-------------------------------------------------- Case System.Xml.XmlNodeType.Text Select Case currentReadLocation Case ReadLocation.inFirstName firstName = xmlReader.Value Case ReadLocation.inLastName lastName = xmlReader.Value Case ReadLocation.inUserID userId = CInt(xmlReader.Value) End Select 'End of Case "System.Xml.XmlNodeType.Text" '--------------------------------------------------- 'Gets called when we have encountered the end of 'an element ' 'We may want to switch our state based on what node 'we are exiting to indicate that we are going back 'to that node's parent '--------------------------------------------------- Case System.Xml.XmlNodeType.EndElement Dim continueParsing As Boolean continueParsing = LoadHelper_EndElementEncountered( _ currentReadLocation) If (continueParsing = False) Then GoTo finished_reading_wanted_data End If Case Else 'There is no harm in having other XML node types, but 'in our sample XML parsing we should note this occurrence MsgBox( _ "Unexpected XML type encountered" + xmlReader.Name) End Select 'End of case statement based current type of XML 'element the parser is on. 'Go to the next node readSuccess = xmlReader.Read() End While 'If we made it to this point without exiting the UserInfo 'XML tag, something went wrong with the XML data we were 'reading. Throw New Exception("Could not find UserInfo in XML!") finished_reading_wanted_data: 'Close the file, we're done with it! xmlReader.Close() End Sub '------------------------------------------------------- 'Helper logic that decides what state we should enter 'when we encounter an exit tag. '------------------------------------------------------- Private Shared Function LoadHelper_EndElementEncountered( _ ByRef currentReadLocation As ReadLocation) _ As Boolean Select Case (currentReadLocation) 'If we are leaving the Name node, we are going back 'up to the UserInfo Case ReadLocation.inName currentReadLocation = ReadLocation.inUserInfo 'If we are leaving the FirstName node, we are going 'back up to the Name node Case ReadLocation.inFirstName currentReadLocation = ReadLocation.inName 'If we are leaving the LastName node, we are going back 'up to the Name node Case ReadLocation.inLastName currentReadLocation = ReadLocation.inName 'If we are leaving the UserID node, we are going back 'up to the UserInfo node Case ReadLocation.inUserID currentReadLocation = ReadLocation.inUserInfo 'If we are leaving the UserInfo node, we have just 'finished reading in the UserID, FirstName, 'and LastName. ' 'We can exit the loop, because we have all the information 'we want! Case ReadLocation.inUserInfo Return False 'We should stop parsing End Select Return True 'Continue parsing End Function Private Shared Sub LoadHelper_NewElementEncountered( _ ByVal nodeName As String, _ ByRef currentReadLocation As ReadLocation) '--------------------------------------------------------- 'We have entered a new element! ' 'What state we can enter is dependent on what state we are 'presently in '--------------------------------------------------------- Select Case (currentReadLocation) 'If we're in the AllMyData node, here are the nodes 'we can enter Case (ReadLocation.inAllMyData) If (nodeName = XML_USERINFO_TAG) Then currentReadLocation = ReadLocation.inUserInfo End If 'If we're in the UserInfo node, here are the nodes 'we can enter Case (ReadLocation.inUserInfo) If (nodeName = XML_USERID_TAG) Then currentReadLocation = ReadLocation.inUserID ElseIf (nodeName = XML_NAMEINFO_TAG) Then currentReadLocation = ReadLocation.inName End If 'If we're in the Name node, here are the nodes 'we can enter Case (ReadLocation.inName) If (nodeName = XML_FIRSTNAME_TAG) Then currentReadLocation = ReadLocation.inFirstName ElseIf (nodeName = XML_LASTNAME_TAG) Then currentReadLocation = ReadLocation.inLastName End If End Select End Sub End Class
|