Chapter
11
.NET XML
XML has taken the software world by storm. Everything from
configuration files and databases (such as SQL Server) to Microsoft Office and
Web Services have the ability to work with XML. In many ways, the .NET
Framework was built with XML in mind. This chapter discusses incorporating XML
into your .NET applications and also offers an overview of XML base classes for
reading, writing, and manipulating XML.
Microsoft has done a good job making .NET and Visual
Studio .NET great tools for working with XML. As already mentioned in Chapter
3, “Introduction to C#”, you can create XML comments in your C# source code and
build Comment Web pages from them. In addition to this, Visual Studio .NET has
an extremely capable tool for working with XML—the XML Designer. This tool
makes it easy to create XML files, schemas, and (from the schemas) ADO.NET
DataSets.
In addition to design-time tools, the .NET Framework class
library has an entire namespace (System.Xml) containing powerful base classes
that allow you to read, write,
and manipulate XML in just about every way imaginable. Before diving into these
tools, I’ll discuss some fundamentals of XML and direct you to some resources
for learning more of
the basics.
XML basics
Why should you care about XML? When you get down to it,
XML is really just a new text-based data format. However, two things make XML a
“big deal”.
The first is every major “player” in the software and
database worlds has agreed to conform to this standard. This in itself is huge
because it breaks down the barriers between software systems written on diverse
platforms. For example, you can pass data or other information in XML format
from a Microsoft application such as Visual FoxPro or .NET to an application
written in a non-Microsoft language such as Java, running on a non-Microsoft UNIX
or Linux platform, and be confident that these platforms and languages have
tools to easily read and manipulate your XML document.
The second reason is that XML is self-describing. Other text
formats such as comma-delimited or tab-delimited files require you to create a
separate word processing document describing each field. You then have to write
a program to read the text file, translate the data to the proper data type,
and store it in your database of choice. This can be a lot of work.
In contrast, an XML document can have a related XML schema
(stored “in line” with the data or stored in a separate file) to
programmatically determine the structure and content of an XML document at
runtime. This means no more writing special programs to import text files into
your applications.
This chapter assumes a basic, working knowledge of XML—for
more information on the basic structure and syntax of XML, check out the .NET
Help topics “Introduction to XML” and “XML Technology Backgrounder”. Another
great resource is the MSDN Online XML Developer Center Web site (http://msdn.microsoft.com/xml/default.asp).
A good book on the subject is “Inside XML” by Steven Holzner (ISBN 0735710201).
Visual FoxPro 8’s new XML support
Visual FoxPro 8 has added support for XML in a
hierarchical format by adding a new XMLAdapter class. This class improves
Visual FoxPro’s ability to interoperate with XML produced from .NET DataSets.
As mentioned in Chapter 7, “Data Access with ADO.NET”, a
DataSet can contain multiple DataTables and you can create relationships
between these tables. VFP 8 has the ability to read hierarchical XML produced
from this kind of DataSet and convert it into separate VFP cursors. In cases
where the hierarchical XML does not represent a collection of related tables,
but is simply a single table representing the result of a multi-table SQL Join
command, then this XML is converted into a single Visual FoxPro cursor.
For details on the XMLAdapter class, check the Visual FoxPro
8 Help file.
Introducing the XML Designer
Visual Studio .NET has an XML Designer making it
incredibly easy to work with XML documents and XML schemas—even if you’re not
an XML expert. Although you can create XML files and schemas using a
plain text editor such as Notepad, the visual tools in the XML Designer make
you far more productive. You’ll also see later in this chapter how you can work
with ADO.NET DataSets in the XML Designer.
The XML Designer has three different viewing modes—XML view,
Schema view, and Data view. You’ll see a sample of each of these views in the
next section
Manually creating a new XML file and schema
The best way to fully understand how the XML Designer
works is to use it. This section takes you through the steps of manually
creating a new XML file and schema. In this example you will create an XML file
(and an associated schema) containing a partial list of the works of
Shakespeare—helping you feel superior in both the technology and literary
fields. Here’s an overview of the main steps:
1. Create
a new, empty XML file.
2. Create
a new, empty Schema file.
3. Use
the designer to create the schema.
4. Associate
the schema and the XML file.
5. Add
data to the XML file.
6. Validate
the XML data.
The following sections detail each of these steps.
Creating a new XML file
Add a new, empty XML file to your project as follows:
1.
From the Project
menu (located in the main menu), select Add
New Item. This displays the Add
New Item dialog
2.
In the Templates
pane, select XML File. Change
the name of the XML file in the Name
text box to “Shakespeare.xml”, and then click the Open
button.
This creates a new XML file and automatically opens it in the
XML Designer. The new XML file contains only one line—the XML header:
<?xml version="1.0"
encoding="utf-8" ?>
This is the XML view of the XML Designer. As you’ll see later
in this chapter, XML view gives you IntelliSense, word completion, member
lists, and color-coding.
Creating a new schema file
Using the Visual Studio .NET XML Designer to create a
schema is similar to using the Table Designer in Visual FoxPro to define the
structure of a table. Follow these steps to add a new, empty XML schema file to
the project:
1.
From the VS .NET main menu, select Project | Add New Item.
This launches the Add New Item dialog.
2.
In the Templates
pane, select XML Schema. Change
the name of the schema file in the Name
text box to “ShakespeareSchema.xsd”, and then click the Open button.
This creates a new schema file and automatically opens it in
the XML Designer in
Schema view. The schema is blank except for the text, To start, drag objects from the Server
Explorer or the Toolbox to the design surface, or right-click here.
This is what you’ll do in the next section.
Designing the schema
Adding elements to a schema is similar to adding fields
in the Visual FoxPro Table Designer—you specify the element name and the type
of data it holds. In this example, you will define three elements of a
Shakespeare play—its name, category, and number of acts.
Make sure the XML schema you just created is the currently
selected tab in the Visual Studio .NET IDE. Next, if your Toolbox is auto-hidden,
hover your mouse pointer over the Toolbox
button and select the XML Schema
tab (Figure 1). If the Toolbox
button is not visible, select View |
Toolbox from the main menu or type the shortcut key sequence
Ctrl+Alt+X.

Figure 1. The XML Schema tab of the VS .NET
Toolbox contains items you can drag and drop on the XML Designer to create an
XML schema.
Table 1 provides a description of each item found in
the XML Schema tab.
Table 1. This
table describes all of the items in the XML Schema tab of the Toolbox.
|
Item
|
Description
|
|
element
|
An XML element
|
|
attribute
|
An element attribute
|
|
attributeGroup
|
An element used to group together a
set of attribute declarations to be included as a group into complex type
definitions.
|
|
complexType
|
A complex type that can include
other elements or attributes.
|
|
simpleType
|
A simple type that can only contain
text—it can’t contain other elements or have attributes.
|
|
group
|
An element group used to declare
how elements appear in a group. A sequence group declares all elements
appear in the specified order, a choice group specifies only one of
the elements in the group occurs, and in an all group, all elements
occur or none at all.
|
|
any
|
An element to extend the XML
document with elements not specified in the schema.
|
|
anyAttribute
|
An attribute to extend the XML
document with attributes not specified in the schema.
|
|
facet
|
A facet element to restrict values
of XML elements and attributes. Some of the most common facets are:
·
enumeration – limits an element to a set of
acceptable values.
·
length – restricts an element value to a
specific length.
·
maxLength – restricts the maximum length of an
element value.
·
minLength – restricts the minimum length of an
element value.
·
pattern – restricts the contents of an XML
element to the specified pattern (i.e. numbers and/or letters).
·
whiteSpace –specifies how whitespace
characters should be treated. The options are: preserve, replace, and
collapse.
|
|
key
|
Used to specify table columns as
primary or unique keys. You need to specify keys to create relations and
constraints
|
|
Relation
|
Allows you to specify relations
between elements
|
Drag and drop an element from the Toolbox
to the design surface. This displays a small grid on the design surface (Figure
2).

Figure 2. The element grid provides a visual tool
for creating schema elements.
Change the default element name from “element1” to
“ShakespearePlay”, and then tab to the second column. The text
“(ShakespearePlay)” automatically appears in the second column. Don’t change
the value of this column (the combo box in this column lists a variety of data
types you can specify for elements). Press the TAB key twice to navigate from
the first row to the center cell of the second row and Type “Name” in this
column. Tab to the third column, open the combo box, and take a quick look at
the list of available data types (Figure 3). Close the combo box,
leaving “string” as the selected item.

Figure 3. You can select the desired data type of
a schema element from a combo box in the XML Designer.
Press the TAB key twice to go to the second column of the
third row. Type “Category” in this cell and accept “string” as the default data
type. Add one more element to the grid named “NumberOfActs” and set its type to
“short”.
To see the results of what you have created so far, click on
the XML tab at the
bottom left of the XML Designer. This changes the designer to XML view and displays
the “behind-the-scenes” raw XML. Within the <xs:schema> element you can
see the ShakespearePlay element with Name, Category, and NumberOfActs child
elements:
<xs:element name="ShakespearePlay">
<xs:complexType>
<xs:sequence>
<xs:element
name="Name" type="xs:string" />
<xs:element
name="Category" type="xs:string" />
<xs:element
name="NumberOfActs" type="xs:short" />
</xs:sequence>
</xs:complexType>
</xs:element>
To save your changes so far, select File | Save ShakespeareSchema.xsd
from the main menu or press Ctrl+S.
Next, create a parent element for ShakespearePlay called
“WorksOfShakespeare”. This element is the root node and allows you to have
multiple ShakespearePlay records in your XML file belonging to the
WorksOfShakespeare element. To create this new parent element, go back to
Schema view by clicking the Schema
tab at the bottom left of the XML Designer.
Drag another “element” from the Toolbox
onto the design surface. Change the default name from “element1” to
“WorksOfShakespeare”. When you press TAB, “(WorksOfShakespeare)” is displayed
in the data type column; accept this default.
To associate the ShakespearePlay element with the
WorksOfShakespeare element, simply drag and drop the ShakespearePlay grid onto
the WorksOfShakespeare grid (it’s easiest to grab the design grid by clicking
on the diamond in the upper left corner). The XML Designer displays a line
between the two design grids representing the parent-child relationship of the
data (Figure 4). If you later want to delete this relationship, you do
so by manually editing the XML in the XML
tab of the designer.

Figure
4. You can create hierarchical relationships between data by dragging and
dropping the design grid containing the child data onto the parent grid.
You can create a relationship between
two elements by right-clicking on one of the elements and selecting Add | New Relation…
from the shortcut menu. This launches the Edit Relation dialog allowing you to set a
variety of properties defining the relationship.
Next, you need to specify how many ShakespearePlay elements
can be added to the WorksOfShakespeare element. To do this, select the
ShakespearePlay grid by clicking on the diamond in the upper left corner. Go to
the Properties Window and set the maxOccurs
property to “unbounded”.
Creating a custom data type
In the previous section, you specified the data type of
the Category element as “string”. This indicates that when you create the
actual XML data, you can set any string value for the play category. In
reality, there are really only a few different categories of Shakespeare
plays—Comedy, History, Tragedy, and Romance. To limit the categories to these
values, you create a new custom data type called PlayCategory.
Drag and drop a simpleType from the Toolbox onto the XML
Designer. This displays another grid on the design surface (Figure 5).
Change the default name from “simpleType1” to “PlayCategory” and leave “string”
as the data type.

Figure 5. You can define your own custom data
types in the XML Designer
Tab to the first column in the second row of the design grid.
From the combo box in this cell select the only item available—facet (Figure
6). You can only use facets to build simple types, because simple types
cannot include elements or attributes.

Figure 6. Facets are used to build simple type
elements
Press the TAB key again to go to the second column in the
second row. Open the
combo box and take a quick look at the available properties, but leave the
default “enumeration” selected.

Figure 7. You can specify facet properties such
as enumeration, length, maxLength, and minLength.
Next, Tab to the second column and enter “Comedy” as the
first enumeration value. Add three more facet enumerations to the grid with the
values “History”, “Tragedy”, and “Romance”. When you’re done, your design grid
should look like the grid shown in Figure 8. You have now defined all of
the possible Shakespearean play categories.

Figure 8. You can create custom enumeration types
to limit the data values that can be entered in a particular XML element.
Now go back to the design grid containing the ShakespearePlay
element and change the data type of Category from “string” to “PlayCategory”
(which now appears in the data type combo box). At this point, save your
changes by clicking the Save toolbar button or by typing Ctrl+S. To see what
the XML for the schema looks like now, click the XML
tab at the bottom left of the XML Designer and you should see the following:
<?xml
version="1.0" encoding="utf-8" ?>
<xs:schema
id="ShakespeareSchema"
targetNamespace="http://tempuri.org/ShakespeareSchema.xsd"
elementFormDefault="qualified"
xmlns="http://tempuri.org/ShakespeareSchema.xsd"
xmlns:mstns="http://tempuri.org/ShakespeareSchema.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType
name="PlayCategory">
<xs:restriction
base="xs:string">
<xs:enumeration
value="Comedy" />
<xs:enumeration
value="History" />
<xs:enumeration
value="Tragedy" />
<xs:enumeration
value="Romance" />
</xs:restriction>
</xs:simpleType>
<xs:element
name="WorksOfShakespeare">
<xs:complexType>
<xs:sequence>
<xs:element
name="ShakespearePlay" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element
name="Name" type="xs:string" />
<xs:element
name="Category" type="PlayCategory" />
<xs:element
name="NumberOfActs" type="xs:short" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Associating the schema with the XML file
Now it’s time to associate the XML file you created
earlier with this new XML schema. To do this, double-click the Shakespeare.xml
file in the Solution Explorer (or select the Shakespeare.xml
tab in the IDE). Next, go to the Properties Window and click the column to the
right of the targetSchema
property. Select “http://tempuri.org/ShakespeareSchema.xsd” from the combo box
(Figure 9).

Figure 9. You associate an XML file with a schema
by specifying a schema in the targetSchema property of the XML file.
This automatically adds the following WorksOfShakespeare
element that references the ShakespeareSchema:
<WorksOfShakespeare
xmlns="http://tempuri.org/ShakespeareSchema.xsd">
</WorksOfShakespeare>
As you can see in this XML element, when you create a new
schema, Visual Studio .NET creates a default namespace “http://tempuri.org/”
(read this as “temp URI”). You can replace this URI with your own URI that
includes your company’s web site URL. For example:
<WorksOfShakespeare
xmlns="http://www.oakleafsd.com/ShakespeareSchema.xsd">
Adding data to the XML file
This section shows two different ways you can manually
add data to the XML file.
The first way is adding data in XML view mode. Position your
cursor between the opening and closing tags of the <WorksOfShakespeare>
element in the Shakespeare.xml file. Next, press the TAB key for indentation
and type the left angled bracket (<). This automatically displays a list of
elements available in this context based on the ShakespeareSchema file (Figure
10).

Figure 10. If you have a schema file associated
with an XML file, you get IntelliSense in the XML Designer for elements and
attributes
At this point in the XML file, the only element available is
ShakespearePlay. Select this item from the list and type the right-angled bracket
(>). The </ShakespearePlay> end tag is automatically inserted into the
XML file for you. Press ENTER to move the end tag to a new line directly below
the start tag.
Add an empty line between the start and end tags, position
your cursor on the empty line, and press TAB to indent. Next, type the
left-angled bracket (<) again. You should see a list of Category, Name, and
NumberOfActs elements. Select the Name element from the list and type the
right-angled bracket (>). The </Name> end tag is automatically
inserted into the XML file for you. Type the text “Othello” (without the
quotation marks) between the opening and closing Name tags.
Press the END key and then the ENTER key to go to the next
line. Type the left-angled bracket again (<), but this time select the
Category element and enter “Tragedy” as the category. Next add a NumberOfActs
element and for the data between the tags, enter “5”. When you’re done, your
XML file should look like this:
<?xml version="1.0"
encoding="utf-8" ?>
<ShakespearePlay xmlns="http://tempuri.org/ShakespeareSchema.xsd">
<Name>Othello</Name>
<Category>Tragedy</Category>
<NumberOfActs>5</NumberOfActs>
</ShakespearePlay>
To see this in Data view, click the Data tab at the bottom of
the XML Designer. The Data view consists of two areas—the Data Tables pane on the
left and the Data pane on the
right (Figure 11).

Figure 11. The XML Designer’s Data view allows
you to use a design grid to easily add data to an XML file.
The Data Tables
pane displays all tables in the XML file. When you select a table, its
associated data displays in the Data
pane. What’s even better is you can use this data grid for adding data to the
XML file! This is the second way you can add data to an XML file from the XML
Designer.
For example, add the following records to the grid (all of Shakespeare’s
plays have five acts—something you can casually mention to impress your friends
at your next “tea and crumpets” party):
Name Category NumberOfActs
---- -------- ------------
The Comedy of Errors Comedy 5
Henry the Fifth History 5
The Tempest Romance 5
To see the XML generated by the records you added to the
grid, select the XML
tab at the bottom left of the XML Designer. Your XML file should look like
this:
<?xml version="1.0"
encoding="utf-8" ?>
<WorksOfShakespeare
xmlns="http://tempuri.org/ShakespeareSchema.xsd">
<ShakespearePlay>
<Name>Othello</Name>
<Category>Tragedy</Category>
<NumberOfActs>5</NumberOfActs>
</ShakespearePlay>
<ShakespearePlay>
<Name>The
Comedy of Errors</Name>
<Category>Comedy</Category>
<NumberOfActs>5</NumberOfActs>
</ShakespearePlay>
<ShakespearePlay>
<Name>Henry the
Fifth</Name>
<Category>History</Category>
<NumberOfActs>5</NumberOfActs>
</ShakespearePlay>
<ShakespearePlay>
<Name>The
Tempest</Name>
<Category>Romance</Category>
<NumberOfActs>5</NumberOfActs>
</ShakespearePlay>
</WorksOfShakespeare>
Validating XML data
To validate the XML data you added, select XML | Validate XML Data from
the menu. If you entered the data correctly, you should see the message “No
validation errors were found” in the status bar at the bottom left of Visual
Studio .NET IDE.
To check if your enumeration limiting the values of the
Category element is working properly, change the value of any category element
to “Romantic Comedy”, which is an invalid value. When you select XML | Validate XML Data again,
you should get an error in the Task
List complaining “The
‘http://tempuri.org/ShakespeareSchema.xsd:Category’ element has an invalid
value according to its data type”.
To get rid of this error, simply restore the original value
of the category element, save changes, and then run the XML validation again.
Creating ADO.NET Typed DataSets from an XML schema
This section assumes you have read Chapter7, “Data
Access with ADO.NET”, which explains what DataSets are and how they are used in
.NET applications.
There are two types of DataSets—typed and untyped. The
difference is simple—a typed DataSet has an associated XML schema and an
untyped DataSet does not. A typed DataSet is a subclass of the .NET DataSet
base class. It supplies methods and properties to access data in a type-safe
way rather than iterating through collections to get to the data you want,
which is much more convenient. For more information on typed and untyped
DataSets see the .NET Help topic “Introduction to DataSets”.
Adding a new DataSet to the project
To add a new DataSet to your project, do the following:
1.
Select Project
| Add New Item from the main menu to display the Add New Item dialog.
2.
In the Templates
pane, select Data Set. Change
the default name of the DataSet in the Name
text box to “ClientProjects.xsd” and click the Open
button.
This creates a new XML schema file named ClientProjects.xsd
and automatically opens it in the XML Designer in Schema view. The schema is
blank except for the text, To
start, drag objects from the Server Explorer or the Toolbox to the design
surface, or right-click here. This schema file is used to define
the structure of the DataSet.
Another new code file named ClientProjects.cs (if you’re
working with C#) or ClientProjects.vb (if you’re working with Visual Basic
.NET) is also added to the project. To see this file, click the Show All Files
icon button in the Solution Explorer and expand the ClientProjects.xsd
node (Figure 12).

Figure 12. When you add a DataSet to a project,
VS .NET adds a schema file used to define the structure of the DataSet as well
as a code file containing the class definition of the DataSet.
This code file contains the actual class definition for the
new ClientProjects DataSet, which can be instantiated when finished and used to
access and manipulate the specified data. The ClientProjects.xsd file is the
schema you will now use to define the structure of the DataSet (the .xsx file
is a VS .NET designer layout file that you can ignore).
Adding tables to the DataSet
In this section you will add elements to the schema to
represent tables and fields in a DataSet. First, make sure that you have the ClientProjects.xsd tab
selected in the IDE, and then follow these steps:
1.
Drag and drop an element from the Toolbox onto the schema
design surface.
2.
Change the default name from “element1” to “Client”.
This represents the Client table and next you will define elements to represent
fields in the table.
3.
Tab to the second column of the second row. Type the
string “ClientID” in this column and press the Tab key. This displays the
default data type “string” in the third column; accept this default.
4.
Add the additional elements as shown in Figure 13
for the Client table.
5.
Drag and drop a second element from the Toolbox onto the schema
design surface.
6.
Change the default name from “element1” to “Project”.
This represents the
Project table.
7.
Add the additional elements as shown in Figure 13 for
the Project table and
save changes.

Figure 13. You can create DataSet tables in the
XML Designer’s Schema view.
Creating primary keys
To create a primary key in the Client table:
1.
Select the ClientID row in the Client design grid by
clicking to the left of the “E”. Right-click on the column and select Add | New Key… from the
shortcut menu. This launches the Edit
Key dialog (Figure 14).
2.
Change the name of the key to “ClientIDKey”.
3.
Make sure the Element
combo box has the “Client” table selected and the Fields combo box has the
“ClientID” field selected.
4.
Select the Dataset
primary key check box and click OK.
After the dialog closes, a key icon displays next to the ClientID element
indicating it has an associated key.
5.
Create a primary key named “ProjectIDKey” for the
ProjectID field in the Project table in the same way you created a key on the
ClientID field in the Client table.

Figure 14. The Edit Key dialog allows you to
create keys on fields in tables.
Creating a relationship between the tables
To create a relationship between the Project and Client
tables:
1.
Right-click anywhere on the Project table and select Add | New Relation… from
the shortcut menu to launch the Edit
Relation dialog (Figure 15).
2.
The default settings shown in the dialog should all be
correct. For example, the default relation Name
should be “ClientProject”. The Parent
element should be set to “Client” and the Child element to
“Project”. Make sure your dialog has the same settings as that dialog shown in
Figure 15.
3.
Click OK
to save the relation.

Figure 15. The Edit Relation dialog allows you to
create relationships between tables in a DataSet.
When the Edit
Relation dialog saves the relation, it displays a relationship
link between the Client and Project tables (Figure 16).

Figure 16. The XML Designer shows key fields and
relationships between tables
in a DataSet.
You can examine the behind-the-scenes XML schema by clicking
the XML tab at the
bottom of the Designer. Your XML schema should look as follows:
<?xml version="1.0"
encoding="utf-8" ?>
<xs:schema
id="ClientProjects"
targetNamespace="http://tempuri.org/ClientProjects.xsd"
elementFormDefault="qualified"
attributeFormDefault="qualified"
xmlns="http://tempuri.org/ClientProjects.xsd"
xmlns:mstns="http://tempuri.org/ClientProjects.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="ClientProjects"
msdata:IsDataSet="true">
<xs:complexType>
<xs:choice
maxOccurs="unbounded">
<xs:element
name="Client">
<xs:complexType>
<xs:sequence>
<xs:element
name="ClientID" type="xs:string" minOccurs="0"
/>
<xs:element name="Name"
type="xs:string" minOccurs="0" />
<xs:element
name="Address" type="xs:string" minOccurs="0"
/>
<xs:element name="City"
type="xs:string" minOccurs="0" />
<xs:element
name="State" type="xs:string" minOccurs="0" />
<xs:element
name="PostalCode" type="xs:string" minOccurs="0"
/>
<xs:element
name="Preferred" type="xs:boolean" minOccurs="0"
/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element
name="Project">
<xs:complexType>
<xs:sequence>
<xs:element
name="ProjectID" type="xs:string" minOccurs="0"
/>
<xs:element
name="ClientID" type="xs:string" minOccurs="0"
/>
<xs:element name="Description"
type="xs:string" minOccurs="0" />
<xs:element
name="StartDate" type="xs:dateTime" minOccurs="0"
/>
<xs:element
name="EndDate" type="xs:dateTime" minOccurs="0"
/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:key name="ClientIDKey"
msdata:PrimaryKey="true">
<xs:selector
xpath=".//mstns:Client" />
<xs:field
xpath="mstns:ClientID" />
</xs:key>
<xs:key name="ProjectIDKey"
msdata:PrimaryKey="true">
<xs:selector xpath=".//mstns:Project"
/>
<xs:field
xpath="mstns:ProjectID" />
</xs:key>
<xs:keyref name="ClientProject"
refer="ClientIDKey">
<xs:selector
xpath=".//mstns:Project" />
<xs:field
xpath="mstns:ClientID" />
</xs:keyref>
</xs:element>
</xs:schema>
Notice the Client and Project elements are peers and both are
direct children of the ClientProject element, which represents the DataSet.
This is because both the Client and Project elements represent a table in the
DataSet. Also, notice the ClientIDKey and ProjectIDKey elements are direct
children of the ClientProject DataSet allowing the key to control unique values
throughout the DataSet.
Creating XML schemas and DataSets from existing data
In the previous sections you learned how to create XML
schemas and DataSets from scratch. The following steps show you how to create
them from existing data, using the SQL Server Northwind database Products
table.
1.
In the Solution Explorer, right-click on the project
you want to add the XML schema to, and select Add
| Add New Item from the shortcut menu. This displays the Add New Item dialog.
2.
In the Add
New Item dialog, select DataSet
in the Templates pane.
Change the Name of the
DataSet schema to “Products.xsd”.
3.
Click the Open
button. This adds a new schema file named Products.xsd to your project as well
as a new DataSet class stored in the Products.cs (C#) or Products.vb (Visual
Basic .NET) file.
4.
In the Server
Explorer, expand the Data
Connections node, and then expand the node for the connection to
the Northwind database. If the Server
Explorer is not visible, select View
| Server Explorer from the main menu.
5.
Expand the Tables
node (Figure 17). You can also expand the Views
or Stored Procedure node
if you want to create a DataSet from these instead.
6.
Drag and drop the Products table onto the schema design
surface. If you only want a subset of fields to appear in the schema, expand
the Products node,
select the desired fields, and drop them on the schema.

Figure 17. You can drag and drop tables, views,
or stored procedures onto the XML Designer in Schema view to create a schema
and DataSet from existing data.
After dropping the Products table on the Schema Designer,
Visual Studio .NET creates a schema file and associated DataSet from the table.
File types in the XML Designer
The XML Designer allows you to edit a wide variety of
XML-based files. Table 2 lists the different viewing modes of the XML
Designer and the types of files supported in each mode. Of particular interest
to Visual FoxPro developers is the Data mode where you can view XML data in a
data grid, much like VFP’s Browse window.
Table 2. This
table lists the three XML Designer viewing modes and the files supported in
each mode.
|
Viewing mode
|
File Types
|
|
XML mode – Edit XML in a
text-editing window with IntelliSense, word completion, member lists, and
color coding
|
.xml – XML files
.xsd – XML schema
.xslt – Extensible Stylesheet
Language (XSL) Transformations
.wsdl – Web Services Description
Language document
.resx – Resource files
.tdl – Template Description
Language files
.wsf – Windows Script Host
.hta – HTML Application file
.disco – XML Web Service static
discovery file
.vsdisco – XML Web Service dynamic
discovery file
.config – Application Configuration
file
|
|
Schema mode – Create and edit XML
schemas and ADO.NET DataSets
|
.xsd
|
|
Data mode – Modify XML data files in a structured data
grid.
|
.xml
|
The next few sections provide an overview of the XML
Designer’s viewing modes. After that you will see practical examples
demonstrating how to use the XML Designer in each of these modes.
XML in the .NET Framework
The System.Xml namespace contains dozens of classes
that allow you to programmatically work with XML. This section gives you an
overview of some of the primary classes to show you the functionality available
to your .NET applications.
Reading XML with the XmlTextReader
The XmlTextReader class provides fast, forward-only
access to XML data. It can read XML from a file, a stream, or TextReader. A
stream is an object used to read data from an outside source into your program
and to write data from your program to an outside source—that source can be as
diverse as a file, a network connection, or an area of memory. A TextReader is
an object that can read a sequential series of characters. The example below
shows you how to read XML from a file.
The first step involves loading the XML file into the
XmlTextReader object. This is easily done by instantiating an XmlTextReader
object and passing the name of the XML document in the class constructor. For
example:
In C#:
XmlTextReader ReadXml = new
XmlTextReader("..\\..\\chapters.xml");
And in Visual Basic .NET:
Dim ReadXml As New
XmlTextReader("..\..\chapters.xml")
There are a variety of methods available for traversing the
XML document. Table 3 lists a few of the more common methods.
Table 3. This
table lists commonly used methods of the XmlTextReader class
|
XmlTextReader method
|
Description
|
|
Read
|
Reads the next node from the
stream.
|
|
ReadStartElement
|
Checks that the current node is an
element and advances to the next. Optionally, you can specify an element name
to verify that the current node is an element with the specified name.
|
|
ReadEndElement
|
Checks that the current node is an
end tag and advances to the next node.
|
|
ReadElementString
|
Returns the data of the current node
and advances to the next node.
|
To show the context where these methods can be used, here is
an example using an XmlTextReader to traverse the Chapters.xml file (one of the
XML files you can find in the sample source code for this book) and display its
contents in a message box.
In C#:
string
ChapterList = "", ChapterID="", ChapterTitle="";
// Open the text file in the XML reader
XmlTextReader ReadXml = new
XmlTextReader("..\\..\\chapters.xml");
// Read the root node of the file
ReadXml.ReadStartElement("Book");
while (true)
{
// Read the next chapter
starting element
ReadXml.ReadStartElement("chapter");
// Read the chapter's
child id element
ChapterID =
ReadXml.ReadElementString();
// Read the chapter's
child title element
ChapterTitle = ReadXml.ReadElementString();
ChapterList += ChapterID +
" - " + ChapterTitle + "\n";
// Read the chapter ending
element
ReadXml.ReadEndElement();
// Move to the next node.
If it's not a chapter element, exit
ReadXml.Read();
if (ReadXml.Name !=
"chapter")
{
break;
}
}
// Close the XML document
ReadXml.Close();
// Display the chapter list
MessageBox.Show(ChapterList,"XmlTextReader");
And in Visual Basic .NET:
Dim ChapterList As String = ""
Dim ChapterID As String = ""
Dim ChapterTitle As String = ""
' Open the text file in the XML reader
Dim ReadXml As New XmlTextReader("..\..\chapters.xml")
' Read the root node of the file
ReadXml.ReadStartElement("Book")
While True
' Read the next chapter
starting element
ReadXml.ReadStartElement("chapter")
' Read the chapter's
child id element
ChapterID =
ReadXml.ReadElementString()
' Read the chapter's
child title element
ChapterTitle =
ReadXml.ReadElementString()
ChapterList += ChapterID
+ " - " + ChapterTitle + ControlChars.Lf
' Read the chapter
ending element
ReadXml.ReadEndElement()
' Move to the next node.
If it's not a chapter element, exit
ReadXml.Read()
If ReadXml.Name <>
"chapter" Then
Exit While
End If
End While
' Close the XML document
ReadXml.Close()
' Display the chapter list
MessageBox.Show(ChapterList, "XmlTextReader")
This code instantiates an XmlTextReader and calls its
ReadStartElement method to read the “Book” root node and advance to the first
“chapter” starting element. In the while loop,
ReadStartElement is used to read the starting “chapter” element and advance to
the next node. The ReadElementString method is used to read the chapter id and
title, automatically advancing to the next node with each call. The call to
ReadEndElement reads the ending “chapter” element and advances to the next
node. The call to the Read method checks if the current node is not a
“chapter” node, and if it’s not, the while loop is
exited.
For more information