Using Functional Construction to Create XML Documents
Listing 4: The complete sample program listing.
Imports System.Data Imports System.Data.SqlClient Imports System.Runtime.CompilerServices Imports System.Text Imports System.Reflection Module Module1 Sub Main() Dim customers As List(Of Customer) = GetCustomers() 'Console.WriteLine(customers.Take(5).Dump) 'Console.ReadLine() Dim xml = ConstructXMLDocument(customers.Take(5)) Console.WriteLine(xml) Console.ReadLine() End Sub Function ConstructXMLDocument(ByVal list _ As IEnumerable(Of Customer)) _ As XElement Return New XElement("Customers", _ From customer In list _ Select New XElement("Customer", _ New XElement("CustomerID", customer.CustomerID), _ New XElement("TerritoryID", customer.TerritoryID), _ New XElement("AccountNumber", _ customer.AccountNumber), _ New XElement("rowguid", customer.RowGuid), _ New XElement("ModifiedDate", customer.ModifiedDate))) End Function Private Function GetCustomers() As List(Of Customer) Dim connectionString As String = _ "Data Source=.\SQLExpress;Initial Catalog=AdventureWorks;" + _ "Integrated Security=True" Dim customers As List(Of Customer) = New List(Of Customer) Using connection As SqlConnection = _ New SqlConnection(connectionString) connection.Open() Dim command As SqlCommand = New SqlCommand( _ "SELECT * FROM Sales.Customer", connection) Dim reader As SqlDataReader = command.ExecuteReader While (reader.Read()) customers.Add(New Customer().Create(reader)) End While End Using Return customers End Function <Extension()> _ Public Function Dump(ByVal list As IEnumerable(Of Customer)) _ As String Dim builder As StringBuilder = New StringBuilder() For Each customer As Customer In list builder.Append(customer.Dump()) builder.AppendLine() Next Return builder.ToString() span style='color:blue'>End Function <Extension()> _ Public Function Dump(ByVal customer As Customer) As String Dim builder As StringBuilder = New StringBuilder() Dim info() As PropertyInfo = _ customer.GetType().GetProperties() For Each prop As Propertyinfo In info Try Console.WriteLine("Name: {0}, Value: {1}", _ prop.Name, _ prop.GetValue(customer, Nothing)) Catch ex As Exception Console.WriteLine("Name: {0}, Value: {1}", _ prop.Name, "none") End Try Next Return builder.ToString() End Function <Extension()> _ Public Function Create(ByVal customer As Customer, _ ByVal reader _ As SqlDataReader) As Customer customer.AccountNumber = customer.SafeRead(reader, _ "AccountNumber", "") customer.CustomerID = customer.SafeRead(reader, _ "CustomerID", -1) customer.TerritoryID = customer.SafeRead(reader, _ "TerritoryID", -1) customer.CustomerType = customer.SafeRead(reader, _ "CustomerType", "S") customer.RowGuid = customer.SafeRead(reader, "rowguid", _ Guid.NewGuid()) customer.ModifiedDate = customer.SafeRead(reader, _ "ModifiedDate", DateTime.Now) Return customer End Function <Extension()> _ Function SafeRead(Of T)(ByVal customer As Customer, _ ByVal reader As SqlDataReader, ByVal fieldName As String, _ ByVal defaultValue As T) As T Try Return Convert.ChangeType(reader(fieldName), _ defaultValue.GetType()) Catch ex As Exception Return defaultValue End Try End Function Public Class Customer Private _customerID AsInteger Public Property CustomerID() As Integer Get Return _customerID End Get Set(ByVal Value As Integer) _customerID = Value End Set End Property Private _territoryID As Integer Public Property TerritoryID() As Integer Get Return _territoryID End Get Set(ByVal Value As Integer) _territoryID = Value End Set End Property Private _accountNumber As String Public Property AccountNumber() As String Get Return _accountNumber End Get Set(ByVal Value As String) _accountNumber = Value EndSet End Property Private _customerType As String Public Property CustomerType() As String Get Return _customerType End Get Set(ByVal Value As String) _customerType = Value End Set End Property Private _rowGuid As Guid Public Property RowGuid() As Guid Get Return _rowGuid End Get Set(ByVal Value As Guid) _rowGuid = Value End Set End Property Private _modifiedDate As DateTime Public Property ModifiedDate() As DateTime Get Return _modifiedDate End Get Set(ByVal Value As DateTime) _modifiedDate = Value End Set End Property End Class End Module
If you need a refresher on extension methods, LINQ, or any of the techniques in this article, you can check out many years of back articles on codeguru.com (in the VB Today column) or developer.com.
Summary
Functional construction basically is a part of LINQ to XML that lets you construct an XML document from any data with one line of code. Because XML is self-describing and text, it is highly portable and highly desirable as a standard technology. Being able to easily move to and from an XML format is also highly desirable.
About the Author
Paul Kimmel is the VB Today columnist for www.codeguru.com and has written several books on object-oriented programming and .NET. Check out his upcoming book LINQ Unleashed for C# due in July 2008. Paul Kimmel is an Application Architect for EDS. You may contact him for technology questions at pkimmel@softconcepts.com.
Lansing is having a free Day of .NET training at Lansing Community College on June 21st. Check out the web site for details. The group likes to think of it as a poor man's TechEd (because it's free), but the content will be excellent.
Copyright © 2008 by Paul T. Kimmel. All Rights Reserved.
Page 3 of 3