The XmlDataDocument Class
The System.Xml namespace also includes the capability to automatically synchronize a DataSet with an equivalent XML file. The XmlDocument class is useful for working with XML via the DOM, but it's not a data-enabled class. To bring the DataSet class into the picture, you need to use an XmlDataDocument class, which inherits from the XmlDocument class. Table 3.4 shows the additional members the XmlDataDocument class adds to the XmlDocument class.
Table 3.4 Additional Members of the XmlDataDocument Class
Member |
Type |
Description |
DataSet |
Property |
Retrieves a DataSet representing the data in the XmlDataDocument |
GetElementFromRow |
Method |
Retrieves an XmlElement representing a specified DataRow |
GetRowFromElement |
Method |
Retrieves a DataRow representing a specified XmlElement |
Load |
Method |
Loads the XmlDataDocument and synchronizes it with a DataSet |
The XmlDataDocument class allows you to exploit the connections between XML documents and DataSets. You can do this by synchronizing the XmlDataDocument (and hence the XML document that it represents) with a particular DataSet. You can start the synchronization process with any of the following objects:
An XmlDataDocument
A full DataSet
A schema-only DataSet
If you have an XML file in an XmlDataDocument object, you can retrieve a DataSet object from its DataSet property. Here's how you might load a DataSet using this technique:
' Create a new XmlTextReader on a file Dim xtr As XmlTextReader = _ New XmlTextReader("Books.xml") ' Create an object to synchronize Dim xdd As XmlDataDocument = New XmlDataDocument() ' Retrieve the associated DataSet Dim ds As DataSet = xdd.DataSet ' Initialize the DataSet by reading the schema ' from the XML document ds.ReadXmlSchema(xtr) ' Reset the XmlTextReader xtr.Close() xtr = New XmlTextReader("Books.xml") ' Tell it to ignore whitespace xtr.WhitespaceHandling = WhitespaceHandling.None ' Load the synchronized object xdd.Load(xtr)
This code performs some extra setup to make sure the DataSet can hold the data from the XmlDataDocument. Even when you're creating the DataSet from the XmlDataDocument, you must still explicitly create the schema of the DataSet before it will contain data. That's because in this technique, you can also use a DataSet that represents only a portion of the XmlDataDocument. In this case, the code takes advantage of the ReadXmlSchema method of the DataSet object to automatically construct a schema that matches the XML document. Because the XmlTextReader object is designed for forward-only use, the code closes and reopens this object after reading the schema so that it can also be used to read the data.
CAUTION
When you use the ReadXmlSchema method of the DataSet object to construct an XML schema for the DataSet, both elements and attributes within the XML document become DataColumn objects in the DataSet.
A second way to end up with a DataSet synchronized to an XmlDataDocument is to start with a DataSet. To use this technique, you simply pass the DataSet (which you have already filled with data) to the XmlDataDocument object's constructor:
' Fill the DataSet SqlDataAdapter1.Fill(DsCustomers, "Customers") ' Retrieve the associated document Dim xdd As XmlDataDocument = _ New XmlDataDocument(DsCustomers)
The third method to synchronize the two objects is to follow a three-step recipe:
Create a new DataSet with the proper schema to match an XML document, but no data.
Create the XmlDataDocument from the DataSet.
Load the XML document into the XmlDataDocument.
One way to manage this is to use an XML schema file. An XML schema file describes the format of an XML file. For example, here's an XML schema description of Books.xml:
<?xml version="1.0" encoding="utf-8" ?> <xs:schema id="Books" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:element name="Books"> <xs:complexType> <xs:choice maxOccurs="unbounded"> <xs:element name="Book"> <xs:complexType> <xs:sequence> <xs:element name="Author" type="xs:string" /> <xs:element name="Title" type="xs:string" /> </xs:sequence> <xs:attribute name="Pages" type="xs:string" /> </xs:complexType> </xs:element> </xs:choice> </xs:complexType> </xs:element> </xs:schema>
Given this schema file, with a name such as Books.xsd, you can construct the corresponding DataSet by calling the ReadXmlSchema method of a DataSet object and from there create the corresponding XmlDataDocument:
' Create a dataset with the desired schema Dim ds As DataSet = New DataSet() ds.ReadXmlSchema("Books.xsd") ' Create a matching document Dim xd As XmlDataDocument = _ New XmlDataDocument(ds) ' Load the XML xd.Load("Books.xml")
The advantage to using this technique is that you don't have to represent the entire XML document in the DataSet schema; the schema only needs to include the XML elements you want to work with. For example, in this case the DataSet does not contain the Publisher column, even though the XmlDataDocument includes that column (as you can verify by inspecting the information in the ListBox control).