I came up with some generic methods to do the job:

Public Shared Function DeserializeXMLToObject(ByVal input As String, ByVal type As System.Type) As Object
  Dim result As Object = Nothing
  Dim serializer As New XmlSerializer(type)
  Try
    result = serializer.Deserialize(New XmlTextReader(New StringReader(input)))
  Catch ex As Exception
    Debug.WriteLine(ex.Message)
  End Try
 
  Return result
End Function
Public Shared Function SerializeObjectToXML(ByVal input As Object, ByVal type As System.Type) As String
  Dim returnXML As String = String.Empty
  Dim serializer As New XmlSerializer(type)
  Dim writer As New StringWriter
  Try
    serializer.Serialize(New XmlTextWriter(writer), input)
    returnXML = writer.ToString()
  Catch ex As Exception
    Debug.WriteLine(ex.Message)
  Finally
    writer.Close()
  End Try
  Return returnXML
End Function

There are a few things to watch out for with the XmlSerilizer:

  • When deserializing, if the xml is not well-formed, then an exception will be thrown.
  • Also when deserializing, if there are empty elements like <author></author> or <author/> it seems to throw an exception. I am guessing that it expects empty elements to just not be in the xml. I have not found a way around this yet.
  • When you send in xml that does not match the object you are trying to deserialize, no exception is thrown, the object is basically empty.

When the XmlSerilizer serializes the object it comes out looking something like this:

<?xml version="1.0" encoding="utf-16"?>
<Books xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Book>
    <Title>David McCarter's VB Tips & Techniques</Title>
  </Book>
</Books>

Where I work, we are saving our xml to hardware devices with limited memory. So the <?xml> element and "xmlns" attributes are taking up limited resources and have to be removed. You would think there would be a property in the XmlSerilizer to omit this extra stuff, but there isn't. So I had to roll my own. I changed the SerilizeObjectToXML call a little and added a new method called CleanXML.

Public Shared Function SerializeObjectToXML(ByVal input As Object, ByVal type As System.Type, ByVal clean As Boolean) As String
  Dim returnXML As String = String.Empty
  Dim serializer As New XmlSerializer(type)
  Dim writer As New StringWriter
  Try
    serializer.Serialize(New XmlTextWriter(writer), input)
    returnXML = writer.ToString()
    If clean Then
      returnXML = CleanXML(returnXML)
    End If
    Catch ex As Exception
      Debug.WriteLine(ex.Message)
    Finally
      writer.Close()
  End Try
  Return returnXML
End Function
  
Private Shared Function CleanXML(ByVal input As String) As String
Dim readerXML As New XmlTextReader(New StringReader(input))
Dim writer As New StringWriter
Dim writerXML As New XmlTextWriter(writer)
Dim returnXML As String = String.Empty
  Try
    'writerXML.WriteStartDocument()
    While readerXML.Read()
      Select Case readerXML.NodeType
        Case XmlNodeType.Element
          writerXML.WriteStartElement(readerXML.Name)
          If (readerXML.HasAttributes) Then
            'Cannot just use writer.WriteAttributes,
            'else it will also emit xmlns attribute              
            While readerXML.MoveToNextAttribute()
              If (readerXML.Name.CompareTo("xmlns") = -1) Then
                writerXML.WriteAttributeString(readerXML.Name, readerXML.Value)
              End If
            End While
            readerXML.MoveToElement()
          End If
          If (readerXML.IsEmptyElement) Then
            writerXML.WriteEndElement()
          End If
        Case XmlNodeType.Text
          writerXML.WriteString(readerXML.Value)
        Case XmlNodeType.CDATA
          writerXML.WriteCData(readerXML.Value)
        Case XmlNodeType.ProcessingInstruction
          writerXML.WriteProcessingInstruction(readerXML.Name, readerXML.Value)
        Case XmlNodeType.Comment
          writerXML.WriteComment(readerXML.Value)
        Case XmlNodeType.EntityReference
          writerXML.WriteEntityRef(readerXML.Name)
        Case XmlNodeType.EndElement
          writerXML.WriteEndElement()
      End Select
    End While
    'writerXML.WriteEndDocument()
    writerXML.Flush()
    returnXML = writer.ToString()
  Finally
    writerXML.Close()
    readerXML.Close()
    writer.Close()
  End Try
  Return returnXML
End Function

The readerXML.Name.CompareTo("xmlns") line in the method above will remove the "xmlns" attributes and the commented out WriteStartDocument and WriteEndDocument calls to the writer will remove the <?xml> element. Now your xml is bare!

But be careful when using this CleanXML, as I just found out, if your classes specify the xml namespace by using the XmlRoot or XmlType attributes, then deserializing won't work unless you put the "xmlns" attribute back in (that is my next task to do after I post this tip).

.NET 2.0 And Generics

 Here is the same code but for .NET 2.0 using generics:

Public Shared Function DeserializeXML(Of T)(ByVal xml As String) As T
  Dim serializer As New Serialization.XmlSerializer(GetType(T))
  Return DirectCast(serializer.Deserialize(New XmlTextReader(New IO.StringReader(xml))), T)
End Function
Public Shared Function SerializeToXML(Of T)(ByVal obj As T) As String
  Dim returnXML As String = String.Empty
  Dim serializer As New Serialization.XmlSerializer(GetType(T))
  Using writer As New IO.StringWriter
    serializer.Serialize(New XmlTextWriter(writer), obj)
    returnXML = writer.ToString()
  End Using
  Return returnXML
End Function

Tip Submitted By: David McCarter


 
Categories: .NET | VB.NET | XML

I came up with some generic methods to do the job:

Public Shared Function DeserializeXMLToObject(ByVal input As String, ByVal type As System.Type) As Object
  Dim result As Object = Nothing
  Dim serializer As New XmlSerializer(type)
  Try
    result = serializer.Deserialize(New XmlTextReader(New StringReader(input)))
  Catch ex As Exception
    Debug.WriteLine(ex.Message)
  End Try
 
  Return result
End Function
Public Shared Function SerializeObjectToXML(ByVal input As Object, ByVal type As System.Type) As String
  Dim returnXML As String = String.Empty
  Dim serializer As New XmlSerializer(type)
  Dim writer As New StringWriter
  Try
    serializer.Serialize(New XmlTextWriter(writer), input)
    returnXML = writer.ToString()
  Catch ex As Exception
    Debug.WriteLine(ex.Message)
  Finally
    writer.Close()
  End Try
  Return returnXML
End Function

There are a few things to watch out for with the XmlSerilizer:

  • When deserializing, if the xml is not well-formed, then an exception will be thrown.
  • Also when deserializing, if there are empty elements like <author></author> or <author/> it seems to throw an exception. I am guessing that it expects empty elements to just not be in the xml. I have not found a way around this yet.
  • When you send in xml that does not match the object you are trying to deserialize, no exception is thrown, the object is basically empty.

When the XmlSerilizer serializes the object it comes out looking something like this:

<?xml version="1.0" encoding="utf-16"?>
<Books xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Book>
    <Title>David McCarter's VB Tips & Techniques</Title>
  </Book>
</Books>

Where I work, we are saving our xml to hardware devices with limited memory. So the <?xml> element and "xmlns" attributes are taking up limited resources and have to be removed. You would think there would be a property in the XmlSerilizer to omit this extra stuff, but there isn't. So I had to roll my own. I changed the SerilizeObjectToXML call a little and added a new method called CleanXML.

Public Shared Function SerializeObjectToXML(ByVal input As Object, ByVal type As System.Type, ByVal clean As Boolean) As String
  Dim returnXML As String = String.Empty
  Dim serializer As New XmlSerializer(type)
  Dim writer As New StringWriter
  Try
    serializer.Serialize(New XmlTextWriter(writer), input)
    returnXML = writer.ToString()
    If clean Then
      returnXML = CleanXML(returnXML)
    End If
    Catch ex As Exception
      Debug.WriteLine(ex.Message)
    Finally
      writer.Close()
  End Try
  Return returnXML
End Function
  
Private Shared Function CleanXML(ByVal input As String) As String
Dim readerXML As New XmlTextReader(New StringReader(input))
Dim writer As New StringWriter
Dim writerXML As New XmlTextWriter(writer)
Dim returnXML As String = String.Empty
  Try
    'writerXML.WriteStartDocument()
    While readerXML.Read()
      Select Case readerXML.NodeType
        Case XmlNodeType.Element
          writerXML.WriteStartElement(readerXML.Name)
          If (readerXML.HasAttributes) Then
            'Cannot just use writer.WriteAttributes,
            'else it will also emit xmlns attribute              
            While readerXML.MoveToNextAttribute()
              If (readerXML.Name.CompareTo("xmlns") = -1) Then
                writerXML.WriteAttributeString(readerXML.Name, readerXML.Value)
              End If
            End While
            readerXML.MoveToElement()
          End If
          If (readerXML.IsEmptyElement) Then
            writerXML.WriteEndElement()
          End If
        Case XmlNodeType.Text
          writerXML.WriteString(readerXML.Value)
        Case XmlNodeType.CDATA
          writerXML.WriteCData(readerXML.Value)
        Case XmlNodeType.ProcessingInstruction
          writerXML.WriteProcessingInstruction(readerXML.Name, readerXML.Value)
        Case XmlNodeType.Comment
          writerXML.WriteComment(readerXML.Value)
        Case XmlNodeType.EntityReference
          writerXML.WriteEntityRef(readerXML.Name)
        Case XmlNodeType.EndElement
          writerXML.WriteEndElement()
      End Select
    End While
    'writerXML.WriteEndDocument()
    writerXML.Flush()
    returnXML = writer.ToString()
  Finally
    writerXML.Close()
    readerXML.Close()
    writer.Close()
  End Try
  Return returnXML
End Function

The readerXML.Name.CompareTo("xmlns") line in the method above will remove the "xmlns" attributes and the commented out WriteStartDocument and WriteEndDocument calls to the writer will remove the <?xml> element. Now your xml is bare!

But be careful when using this CleanXML, as I just found out, if your classes specify the xml namespace by using the XmlRoot or XmlType attributes, then deserializing won't work unless you put the "xmlns" attribute back in (that is my next task to do after I post this tip).

.NET 2.0 And Generics

 Here is the same code but for .NET 2.0 using generics:

Public Shared Function DeserializeXML(Of T)(ByVal xml As String) As T
  Dim serializer As New Serialization.XmlSerializer(GetType(T))
  Return DirectCast(serializer.Deserialize(New XmlTextReader(New IO.StringReader(xml))), T)
End Function
Public Shared Function SerializeToXML(Of T)(ByVal obj As T) As String
  Dim returnXML As String = String.Empty
  Dim serializer As New Serialization.XmlSerializer(GetType(T))
  Using writer As New IO.StringWriter
    serializer.Serialize(New XmlTextWriter(writer), obj)
    returnXML = writer.ToString()
  End Using
  Return returnXML
End Function

Tip Submitted By: David McCarter


 
Categories: XML

To download go to: http://go.microsoft.com/?linkid=5559918

 


 
Categories: .NET | Csharp | dotNetDave | Link | VB.NET | XML

February 25, 2004
@ 05:09 PM

This update contains Microsoft XML (MSXML) functionality that will allow applications using MSXML to continue to function correctly after security update 832894, Security Update for Internet Explorer, has been applied. After you install this item, you may have to restart your computer. Once you have installed this item, it cannot be removed.

 

4.0 Service Pack 2: http://www.microsoft.com/downloads/details.aspx?familyid=341caf5f-0cdd-47a8-af5d-91e14fcf7a0d&displaylang=en

 

2.6: http://www.microsoft.com/downloads/details.aspx?familyid=2b0505c3-8509-4cae-865f-e29a41fe65bf&displaylang=en

 

2.5: http://www.microsoft.com/downloads/details.aspx?familyid=4a14fca1-5c2f-4cf1-993e-5e156c33c083&displaylang=en


 
Categories: XML

This Toolkit offers functionality similar to the MSDN SOAP Toolkit sample, which has been available for several months, but is a fully Microsoft supported product. This Toolkit replaces the old MSDN SOAP Toolkit.

 

http://www.microsoft.com/downloads/details.aspx?familyid=147ed727-0be8-48a1-b1da-d50b1ea582cb&displaylang=en

 

SOAP Toolkit 2.0 Redistributable Files:

http://www.microsoft.com/downloads/details.aspx?familyid=d4490e52-5f6e-4127-9dc7-88b7c8f83b74&displaylang=en


 
Categories: Link | Web Services | XML

October 17, 2003
@ 01:51 AM

SQLXML enables XML support for your SQL Server Database. It allows developers to bridge the gap between XML and relational data. You can create XML View of your existing relational data and work with it as if it was an XML file. SQLXML allows you to:

  • Build Web Services with SQL Server 2000
  • Build Web sites to publish data from SQL Server
  • Query relational database with XPath
  • Update relational data as if it was XML
  • Load XML into SQL Server
  • Query SQL Server via URLs, OLEDB/ADO or .NET Managed Classes

SP2 includes many fixes since the SP1 release including:

Identiy Propagation for XML Bulkload

Null Support for Web Services when used with Visual Studio .NET 2003

http://www.microsoft.com/downloads/details.aspx?FamilyID=4c8033a9-cf10-4e22-8004-477098a407ac&DisplayLang=en


 
Categories: ADO.NET | News | XML

September 9, 2003
@ 01:18 AM
Categories: dotNetDave | Link | Web Services | XML

The Microsoft® XML Parser (MSXML) 3.0 SP4 release offers a number of bug fixes and security fixes over the previous MSXML 3.0 SP releases. All MSXML 3.0 releases provide:

  • Server-safe HTTP access
  • Complete implementation of XSL Transformations (XSLT) and XML Path Language (XPath)
  • Changes to the Simple API for XML (SAX2) implementation, including new SAX2 helper classes with even higher conformance with World Wide Web Consortium (W3C) standards and the OASIS Test Suite.

http://www.microsoft.com/downloads/details.aspx?familyid=c0f86022-2d4c-4162-8fb8-66bfc12f32b0&displaylang=en


 
Categories: XML

One of the great new features with SQL Server 2000 is that it can directly output XML from a stored procedure. Then as a developer, you just need to deal with an xml document and all if the built-in features. The code below makes it easy to get xml from a stored procedure or an SQL statement using "FORM XML AUTO" at the end.

Dim pobjSQLConnection As New SqlClient.SqlConnection(ConfigurationSettings.AppSettings("dbconnect")) 
Dim pobjSQLCommand As SqlClient.SqlCommand
Dim pobjXMLReader As System.Xml.XmlReader
Dim pobjXML As New System.Xml.XmlDataDocument()
  Try
    pobjSQLConnection.Open()
    pobjSQLCommand = pobjSQLConnection.CreateCommand
    pstrSQL = "sp_GETCustomersNamesAsXML"
    pobjSQLCommand.CommandText = pstrSQL.ToString
    pobjXMLReader = pobjSQLCommand.ExecuteXmlReader()
    pobjXMLReader.Read()
    pobjXML.LoadXml(pobjXMLReader.ReadOuterXml)
    pobjSQLConnection.Close()
  Catch
    'Blow by errors if you want
  Finally
    pobjSQLCommand.Dispose()
    pobjSQLConnection.Dispose()
  End Try

Tip Submitted By: David McCarter


 
Categories: ADO.NET | XML