Recipe 14.23. Creating an XML DocumentProblemYou need to build an XML file that contains important configuration or processing data, and you aren't excited about doing all the string concatenation yourself. SolutionSample code folder: Chapter 14\GenerateXMLContent
Use the XML document creation tools in the
System.XML
namespace to generate the XML. This namespace includes a few different ways of building XML content. One of the simplest
DiscussionThis recipe's sample code builds a simple program that outputs a list of email recipients in XML format. It groups recipients by the desired email format, either HTML or plain text. Here is a sample of the generated XML content: <?xml version="1.0"?> <emailData> <emailRecipients mailType="HTML"> <recipient> <name>John Smith</name> <address>jsmith@fakeemail.com</address> </recipient> <recipient> <name>Jane Jones</name> <address>jane.jones@dontmailme.com</address> </recipient> </emailRecipients> <emailRecipients mailType="Text"> <recipient> <name>Brenda Wong</name> <address>puppyfriend@ilikedogs.net</address> </recipient> </emailRecipients> </emailData> Create a new Windows Forms application, and add the following controls to Form1 :
Add informational labels if desired, and arrange the controls so that Form1 looks like the form in Figure 14-19. Figure 14-19. Controls for the XML-generation sample
Now add the following source code to Form1 's class template:
Public Class RecipientData
' ----- A simple class to hold the basics of an address.
Public EmailType As String
Public EmailName As String
Public EmailAddress As String
Public Sub New(ByVal newType As String, _
ByVal newName As String, ByVal newAddress As String)
' ----- Constructor to build the new record.
EmailType = newType
EmailName = newName
EmailAddress = newAddress
End Sub
Public Overrides Function ToString( ) As String
' ----- Display a nicely formatted address.
Return EmailName & " <" & EmailAddress & ">"
End Function
End Class
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
' ----- Add the types of email content.
EmailType.Items.Add("HTML")
EmailType.Items.Add("Text")
EmailType.SelectedIndex = 0
End Sub
Private Sub DeleteEmail_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles DeleteEmail.Click
' ----- Remove the selected email address.
If (AllRecipients.SelectedIndex <> ListBox.NoMatches) Then _
AllRecipients.Items.Remove(AllRecipients.SelectedItem)
End Sub
Private Sub AddEmail_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles AddEmail.Click
' ----- Add an email recipient. Check for missing data.
If (RecipientName.Text.Trim = "") Then
MsgBox("Please supply a recipient name.")
Return
End If
If (RecipientAddress.Text.Trim = "") Then
MsgBox("Please supply a recipient address.")
Return
End If
' ----- Add this recipient to the list.
AllRecipients.Items.Add(New RecipientData( _
EmailType.Text, RecipientName.Text, _
RecipientAddress.Text))
' ----- Get ready for a new entry.
RecipientName.Clear( )
RecipientAddress.Clear( )
RecipientName.Focus( )
End Sub
Private Sub SaveFile_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles SaveFile.Click
' ----- Save the
XML content.
Dim emailSet As Xml.XmlDocument
Dim emailDeclare As
Xml.XmlDeclaration
Dim emailRoot As Xml.XmlElement
Dim emailGroup As Xml.XmlElement
Dim emailRecipient As Xml.XmlElement
Dim emailDetail As Xml.XmlElement
Dim counter As Integer
Dim useType As String
Dim scanEmail As Object
Dim oneEmail As RecipientData
' ----- Check for missing data.
If (AllRecipients.Items.Count = 0) Then
MsgBox("Please enter at least one recipient.")
Return
End If
If (XMLFile.Text.Trim = "") Then
MsgBox("Please specify the output file.")
Return
End If
' ----- Warn if the file exists.
If (My.Computer.FileSystem.FileExists(XMLFile.Text)) Then
If (MsgBox("The file exists. Overwrite?", _
MsgBoxStyle.YesNo Or MsgBoxStyle.Question) <> _
MsgBoxResult.Yes) Then Return
Try
Kill(XMLFile.Text)
Catch ex As Exception
MsgBox("Could not replace the file. " & ex.Message)
Return
End Try
End If
' ----- Start the XML document with an XML declaration.
emailSet = New Xml.XmlDocument
emailDeclare = emailSet.CreateXmlDeclaration("1.0", _
Nothing, String.Empty)
emailSet.InsertBefore(emailDeclare, _
emailSet.DocumentElement)
' ----- Add in the root <emailData> element.
emailRoot = emailSet.CreateElement("emailData")
emailSet.InsertAfter(emailRoot, emailDeclare)
' ----- Scan through the recipients, once for each type.
For counter = 0 To EmailType.Items.Count - 1
' ----- Prepare for this pass.
useType = EmailType.Items(counter)
emailGroup = Nothing
For Each scanEmail In AllRecipients.Items
oneEmail = CType(scanEmail, RecipientData)
If (oneEmail.EmailType = useType) Then
' ----- Found a recipient in this group.
' Add the group if needed.
If (emailGroup Is Nothing) Then
emailGroup = emailSet.
CreateElement( _
"emailRecipients")
emailGroup.SetAttribute("mailType", useType)
emailRoot.AppendChild(emailGroup)
End If
' ----- Build the new output entry.
emailRecipient = emailSet.CreateElement( _
"recipient")
emailGroup.AppendChild(emailRecipient)
emailDetail = emailSet.CreateElement("name")
emailDetail.InnerText = oneEmail.EmailName
emailRecipient.AppendChild(emailDetail)
emailDetail = emailSet.CreateElement("address")
emailDetail.InnerText = oneEmail.EmailAddress
emailRecipient.AppendChild(emailDetail)
End If
Next scanEmail
Next counter
' ----- Write out the
XML content.
Try
emailSet.Save(XMLFile.Text)
MsgBox("XML content saved.")
Catch ex As Exception
MsgBox("Could not write the XML content. " & _
ex.Message)
End Try
End Sub
To use the program, select an email type (HTML or Text) from the Type drop-down list, enter in a recipient name and email address in the two text fields next to the drop-down, and then click the Add button to add the recipient to the list. Repeat as needed. When you have added enough recipients, supply an output filename in the XML File field, and then click the Save button. Most of this recipe's sample code lets you build the list of email recipients in a ListBox control. The embedded RecipientData class helps organize the content stored in each ListBox item. The real XML work happens in the Click event handler for the SaveFile button. After performing some quick verification, the method creates a new XmlDocument to store the new XML content. For each node in the output, it then creates XmlElement objects using the XmlDocument.CreateElement() method. This method generates a generic XML element, representing a standard XML tag. It adds attributes to the element via the XmlElement.SetAttribute() method. These completed elements are then inserted into the existing XmlDocument structure relative to other existing nodes. The various uses of the InsertBefore(), InsertAfter() , and AppendChild() methods in the sample code show how you can position elements as you need them. Besides CreateElement(), XmlDocument includes other Create … methods that generate a variety of XML-specific content entities. For example, the CreateXmlDeclaration() method is used in the sample code to generate the <?xml version="1.0"?> tag at the start of the document:
emailDeclare = emailSet.CreateXmlDeclaration("1.0", _
Nothing, String.Empty)
Once elements have been added to the XmlDocument , you can traverse them using any of the supported XML tools, such as XPath. See AlsoRecipes 14.22 and 14.24 discuss other methods of working with XML content. |