Applied XML Programming for Microsoft .NET
Dino Esposito Microsoft Press
A Division of Microsoft Corporation One Microsoft Way Redmond, Washington 98052-6399
Copyright © 2003 by Dino Esposito
All rights reserved. No part of the contents of this book may be reproduced or
transmitted in any form or by any means without the written permission of the publisher.
Library of Congress Cataloging-in-Publication Data [ pending.]
Esposito, Dino, 1965-
Applied XML Programming for Microsoft .NET / Dino Esposito
p. cm.
Includes index.
ISBN 0-7356-1801-1
1. XML (Document markup language) 2. Microsoft .NET. I. Title.
QA76.76.H94 E85 2002
005.7'2--dc21 2002029546
Printed and bound in the United States of America.
1 2 3 4 5 6 7 8 9 QWT 7 6 5 4 3 2
Distributed in Canada by H.B. Fenn and Company Ltd.
A CIP catalogue record for this book is available from the British Library.
Microsoft Press books are available through booksellers and distributors worldwide. For
further information about international editions, contact your local Microsoft Corporation
office or contact Microsoft Press International directly at fax (425) 936-7329. Visit our
Web site at www.microsoft.com/mspress
. Send comments to:
<[email protected]
>.
one reason or another the project never took off. So I'd like to start by saying thanks to
the people who believed in a fairly confused book idea and worked to make it happen.
These people are Anne Hamilton and Jeannine Gailey. (By the way, all the best,
Jeannine!)
Lynn Finnel brought the usual fundamental contribution as project editor. As Lynn
originally described her role in the first e-mail we exchanged, being an editor is a
delicate art, as you have to reconcile the needs of many people while meeting your own
deadlines. Thanks again, Lynn.
And a warm thanks goes to Jennifer Harris, who edited the book, and technical
reviewers Marc Young, Jim Fuchs, Julie Xiao, and Jean Ross.
Other people were involved with this book, mostly as personal reviewers. Francesco
Balena tested some of the code and provided a lot of insight. In particular, Giuseppe
Dimauro and Giuseppe Guerrasio helped to figure out the intricacies of the
XmlSerializer class, and Ralph Westphal did the same with custom readers. Kenn
Scribner has been the ideal extension to the MSDN documentation about Web
services. Rainer Heller of Siemens offered a really interesting perspective on Web
services interoperability. It was nice to discuss Web services in the more general
context of a conversation based on the World Football Championships—an indirect
demonstration that Web services are still interoperable today!
Thanks to all the Wintellect guys, and Jason Clark and Jeffrey Richter, in particular, for
their friendly and effective support.
And now my family. I've noticed that many authors, when writing acknowledgments,
promise their families that they will never repeat the experience. Although rewarding for
themselves, they explain, writing a book is too hard on the rest of the family to be
repeated. I'll be honest and sincere here. So, Silvia, and Francesco and Michela, set
your mind at rest. I will do all I can to write even more books. But I love you all beyond
imagination. —'til the next book
Chapter 10 - Stateful Data Serialization
Part IV - Applications Interoperability
Chapter 11 - XML Serialization
Chapter 12 - The .NET Remoting System
Chapter 13 - XML Web Services
Chapter 14 - XML on the Client
Chapter 15 - .NET Framework Application Configuration
Afterword
Index
List of Figures
List of Tables
List of Sidebars 1
Introduction
It was about five years ago, a few days after I finished my first book, when the publisher
came to me with a rather enticing proposal: "Why don't you start thinking about a new
book?" Now I realize that all publishers make this sort of proposition, but at the time the
proposal was definitely alluring, and a clear signal—I thought—of appreciation.
specialized dialects like Simple Object Access Protocol (SOAP) and XPath. As a result,
XML programming requires ad hoc tools for reading and writing in these dialects; all the
better if the tools are tightly integrated into some sort of programming framework.
Effective XML programming requires that you be able to generate XML in a more
powerful way than merely concatenating strings. The XML API must be extensible
enough to accommodate pluggable technologies and custom functionalities. And it
must be serializable and integrate well with other elements of data storage and
exchange, including databases, complex data types (arrays, tables, and lists), and—
why not?—visual user interface elements. In simple terms, XML must no longer be a
distinct API bolted onto the core framework, but instead be a fully integrated member of
the family. This is just what XML is in the Microsoft .NET Framework. And this book is
about XML programming with the .NET Framework.
2
What Is This Book About?
This book explores the array of XML tools provided by the .NET Framework. XML is
everywhere in the .NET Framework, from remoting to Web services, and from data
access to configuration. In the first part of this book, you'll find in-depth coverage of the
key classes that implement XML in the .NET platform. Readers and writers, validation,
and schemas are discussed with samples and reference information. Next the book
moves on to XPath and XSL Transformations (XSLT) and the .NET version of the XML
Document Object Model (XML DOM).
The final part of this book focuses on data access and interoperability and touches on
SQL Server 2000 and its XML extensions and .NET Remoting and its cross-platform
counterpart—XML Web services. You'll also find a couple of chapters about XML
configuration files and XML data islands and browser/deployed managed controls. What Does This Book Cover?
This book attempts to answer the following common questions:
Web at the following address: http://www.microsoft.com/mspress/books/6235.asp. To
open the Companion Content page, click on the Companion Content link in the More
Information box on the right side of the page.
Although all the code shown in this book is in C#, the sample files are available both in
C# and in Microsoft Visual Basic .NET. Here are some of the more interesting
examples:
An XML reader that reads CSV files and exposes their contents as XML
An extended version of the XML DOM that detects changes to the disk file and
automatically refreshes its data
A Web service that offers dynamically created images
An XML reader class with writing capabilities
A class that serializes DataTable objects in a true binary format
A tool to track the behavior of the XML serializer class
A ListView control that retrieves its data from the host HTML page
These and other samples will get you on your way to XML in the .NET Framework.
3
What Do I Need to Use This Book?
Most of the examples in this book are Windows Forms or console applications. The key
requirements for running these applications are the .NET Framework and Microsoft
<[email protected]>
In addition, you can contact the author at the Wintellect (http://www.win-tellect.com
) and
VB2-The-Max (http://www.vb2themax.com) Web sites. Support
Every effort has been made to ensure the accuracy of this book and the contents of the
sample files. Microsoft Press provides corrections for books through the Web at the
following address:
http://www.microsoft.com/mspress/support/
To connect directly to the Microsoft Press Knowledge Base and enter a query regarding
a question or issue that you might have, go to:
http://www.microsoft.com/mspress/support/search.asp
If you have comments, questions, or ideas regarding this book or the sample files,
please send them to Microsoft Press using either of the following methods:
Postal mail:
4
Microsoft Press
Attn:Microsoft .NET XML Programming Editor
One Microsoft Way
Redmond, Wa 98052-6399
E-mail:
<[email protected]>
Please note that product support is not offered through the above mail addresses. For
support information, please visit the Microsoft Product Support Web site at
http://support.microsoft.com
work with XML documents and related technologies at various levels and in strict
accordance with the most recent World Wide Web Consortium (W3C) standards and
recommendations. The XML support available in the .NET Framework covers XML 1.0,
XML namespaces, Document Object Model (DOM) Level 2 Core, XML Schema
Definition (XSD) Language, Extensible Stylesheet Language Transformations (XSLT),
and XPath expressions. In addition, XML core classes are tightly integrated with other
key portions of the .NET Framework, including data access, serialization, and
applications configuration.
In this chapter, we'll take an overall look at XML as it is used in the .NET Framework. In
particular, we'll focus on the new and innovative parsing model based on the concept of
reader components. This first chapter is aimed at providing you with the big picture of
the .NET Framework XML API, the key elements of transition from the previous
Component Object Model (COM)-based Win32 API, and a bird's-eye view of the
interconnections between XML and various parts of the .NET Framework. XML in the .NET Framework
The .NET Framework XML core classes can be categorized according to their
functions: reading and writing documents, validating documents, navigating and
selecting nodes, managing schema information, and performing document
transformations. The assembly in which the whole XML .NET Framework is
implemented is system.xml.dll.
The most commonly used namespaces are listed here:
System.Xml
System.Xml.Schema
System.Xml.XPath
http://www.w3.org/TR/xpath
XSLT
http://www.w3.org/TR/xslt
SOAP 1.1
http://www.w3.org/TR/SOAP
As a data exchange technology, XML is fully and tightly integrated into the .NET
Framework. Table 1-2 provides a quick schematic view of the main areas of the .NET
Framework in which significant traces of XML are clearly visible. Each area includes
numerous classes and provides a set of application-level functions.
Table 1-2: Areas of the .NET Framework in Which XML Is Key
Category Description
ADO.NET
Data container objects (for example, the DataSet object)
are always transferred and remoted via XML. The .NET
Framework also provides for two-way synchronized
binding between data exposed in tabular format and
XML format.
Configuration Application settings are stored in XML files, making use
of predefined and user-defined section readers. (More
on readers later.)
Remoting Remote .NET Framework objects can be accessed by
using SOAP packets to prepare and perform the call.
Web services SOAP is a lightweight XML protocol that Web services
use for the exchange of information in a decentralized,
distributed environment. Typically, you use SOAP to
invoke methods on a Web service in a platform-
independent fashion.
serializing documents to and from XML format will not be available
until DOM Level 3 Core achieves the status of a W3C
recommendation. As of summer 2002, DOM Level 3 Core is
qualified as a work in progress. The publicly available draft defines
the specification for a pair of Load and Save methods designed to
enable loading XML documents into a DOM representation and
saving a DOM representation as an XML document. For more
information, refer to http://www.w3.org/TR/2002/WD-DOM-Level-3-
Core-20020409.
A known parser that already provides an experimental
implementation of DOM Level 3 Core is IBM's XML Parser for Java
(Xml4J). See http://www.alphaworks.ibm.com/tech/xml4j for more
information.
Core Classes for Parsing
Regardless of the underlying platform, the available XML parsers fall into one of two
main categories: tree-based parsers and event-based parsers. Each parser category is
designed according to a different philosophical approach and, subsequently, has its
own pros and cons. The two categories are commonly identified with their two most
popular implementations: XMLDOM and Simple API for XML (SAX). The XMLDOM
parser is a generic tree-based API that renders an XML document as an in-memory
structure. The SAX parser provides an event-based API for processing each significant
element in a stream of XML data.
Conceptually speaking, a SAX parser is diametrically opposed to an XMLDOM parser,
and the gap between the two models is indeed fairly large. XMLDOM seems to be
clearly defined in its set of functionalities, and there is not much more one can
reasonably expect from the evolution of this model. Regardless of whether you like the
XMLDOM model or find it suitable for your needs, you can't really expect to radically
improve or change its way of working. In a certain sense, the down sides of the
9
XPath and XSL.
XML and ADO.NET
The interaction between ADO.NET classes and XML documents takes one of two
forms:
Serialization of ADO.NET objects (in particular, the DataSet object) to
XML documents and corresponding deserialization. Data can be saved to
XML in a variety of formats, with or without schema information, as a full
snapshot of the in-memory data including pending changes and errors, or
with just the current instance of the data.
A dual-access model that lets you access and update the same piece of
data either through a hierarchical programming interface or using the
ADO.NET relational API. Basically, you can transform a DataSet object
into an XMLDOM object and view the XMLDOM's subtrees as tables
merged with the DataSet object's tables.
The ADO.NET DataSet class represents the only .NET Framework object that can be
natively saved to XML. The XML representation of a DataSet object can have two
different layouts: the ADO.NET normal form and the DiffGram format. In particular, the
DiffGram format describes the history of the data and all recent changes. Each
changed row in each table is represented by two nodes: the first node contains the
10
snapshot of the row as it was originally read, and the second node contains the current
values. The DiffGram represents a snapshot of the DataSet state and contents at a
given moment. To write DiffGrams, ADO.NET uses an XmlWriter object.
The integration of and interaction between XML and ADO.NET classes is discussed in
Chapter 8.
Application Configuration
custom sections with custom elements. By default, however, the AppSettingsReader
class supports only settings expressed in a few formats, such as name/value pairs and
a single tag with as many attributes as needed. This schema fits the bill in most cases,
but when you have complex structured information, it soon becomes insufficient.
Information is read from a section using special objects called section handlers. If no
predefined section structure fits your needs, you can provide a tailor-made
configuration section handler to read your own XML data, as shown here:
<configuration>
<configSections>
<section name="MySection"
type="MySectionHandlerClass, assembly" />
</configSections>
11
<MySection>
⋮
</MySection>
</configuration>
A configuration section handler is simply a .NET Framework class that parses a
particular XML fragment extracted from the CONFIG file. We'll look at custom section
handlers in more detail in Chapter 15.
Interoperability
XML is key to making .NET Framework applications interoperate with each other and
with external applications running on other software and hardware platforms. XML
interoperability is a sort of blanket term that covers three .NET-specific technologies:
XML Web services, remoting, and XML object serialization.
By rolling functionality into an XML Web service, you can expose the functionality to
any application on the Web that, irrespective of platform, speaks HTTP and
understands XML. Based on open standards (HTTP and XML, but also SOAP), XML
meant using the COM-based MSXML, now available in version 4.0, SP1. It goes
12
without saying that Microsoft is still strongly committed to supporting XML the COM
way, although this does not necessarily mean that we are going to have an MSXML 5.0
anytime soon. However, MSXML 4.0 represents an excellent parser for the Windows
platform and has been updated to support W3C final recommendations for the XML
Schema.
COM and .NET Framework XML Core Services
The first difference between MSXML and .NET Framework XML core classes that
catches the eye is the fact that while MSXML supports XMLDOM and SAX parsers, the
.NET Framework supplies an XMLDOM parser and XML readers and writers. (More on
readers shortly.) This is just the most remarkable example of a common pattern,
however. Quite a few key features of MSXML are apparently not supported in the .NET
Framework XML core classes, but this hardly results in a loss of programming power.
In general, the biggest (and perhaps the only significant) difference between MSXML
and .NET Framework XML classes is that the former represents a set of classes fully
integrated into an all-encompassing, self-contained framework. Several functionalities
that MSXML has to provide on its own come for free in the .NET Framework from other
compartments. If you happen to use a certain MSXML function and you don't find a
direct counterpart in the .NET Framework, check out the MSDN documentation before
you panic. In the paragraphs that follow, we'll look at a few examples of .NET
Framework functionality that provide the equivalent of some MSXML functionality.
MSXML supports asynchronous loading and validation while parsing. The .NET
Framework XMLDOM parser, centered around the XmlDocument class, does not
directly provide the same features, but proper use of the resources of the .NET
Framework will let you obtain the same final behavior anyway.
MSXML also provides for a multithreaded HTTP client (the XmlHttp object) capable of
issuing both synchronous and asynchronous calls to a remote URL. A similar feature is
certainly available in the .NET Framework, but it has nothing to do with XML classes. If
fit into the .NET Framework type system. After the importation is complete, the original
COM object is ready for use in the .NET Framework, and more importantly, it has
preserved the original interface while adding some .NET Framework-specific members
such as ToString and GetType. In the end, for a Microsoft Visual Basic 6.0 programmer
who happens to use Visual Basic .NET, the code to be written is nearly identical.
Note
To generate a .NET wrapper class for a COM object, you can also
use the tlbimp.exe utility from the command line. This utility gives
you full control over the entire process, and by using command-line
switches, you can intervene in many useful areas, including the
(strong) name of the assembly and the wrapping namespace.
Although importing MSXML functionality into a .NET application is straightforward, you
must have a good reason for doing so. Jumping continuously in and out of the .NET
common language runtime (CLR) can result in a performance hit—not to mention the
fact that you end up using a programming model that, although perfectly functional, is
not the best suited for the surrounding environment. The .NET Framework XML API
The essence of XML in the .NET Framework is found in two abstract classes—
XmlReader and XmlWriter. These classes are at the core of all other .NET Framework
XML classes, including the XMLDOM classes, and are used extensively by various
subsystems to parse or generate XML text. For example, ADO.NET data adapters
retrieve the data to store in a DataSet object using a database reader, and the DataSet
object serializes its contents to the DiffGram format using an XmlTextWriter object,
which derives from XmlWriter.
XML readers and writers constitute the primitive I/O functions for XML documents and
are used to build more sophisticated functionalities. So overall, you have two possible
mode, whereas writers accomplish their tasks operating in write-only mode.
.NET Framework Readers and Writers
In the .NET Framework, the classes available from the System.IO namespace provide
for both synchronous and asynchronous read/write operations on two distinct
categories of data: streams and files. A file is an ordered and named collection of bytes
and is persistently stored to a disk. A stream represents a block of bytes that is read
from, and written to, a data store. The data store can be based on a variety of storage
media, including memory, disk files, and remote URLs. A stream is a kind of superset of
a file, or in other words, a file that can be saved to a variety of storage media including
memory. To work with streams, the .NET Framework defines several flavors of reader
and writer classes. Figure 1-1
shows how each class relates to the others.
15
Figure 1-1: Streams can be read and written using made-to-measure reader and writer
classes.
The base classes are TextReader, TextWriter, BinaryReader, BinaryWriter, and
Stream. With the exception of the binary classes, all of these classes are marked as
abstract (MustInherit, if you speak Visual Basic) and cannot be directly instantiated in
code. You can use abstract classes to reference living instances of derived classes,
however.
In the .NET Framework, base reader and writer classes find a number of concrete
implementations, including StreamReader and StringReader and their writing
counterparts. By design, reader and writer classes work on top of .NET streams and
provide programmers with a customized user interface able to handle a particular type
of underlying data or file format. Although each specific reader or writer class is tailor-
from byte to byte or from record to record. When viewed from the perspective of
readers, an XML document ceases to be a tagged text file and becomes a serialized
collection of nodes. Such a cursor model is specific to the .NET platform, and to date,
you will not find a similar programming API available for other platforms, including
Microsoft Win32.
16
Readers vs. XMLDOM
XML readers don't require you to keep more data in memory than you actually need.
When you open the XML document, a simple logical pointer that corresponds to a node
is returned. You can easily skip over nodes to locate the one you need. In doing so, you
don't tax in any way the application's memory with extra data other than that required to
bufferize the currently selected node.
In contrast, the XMLDOM—a full read/write parser model—has the drawback that it
might require a significant memory footprint and a long time to set up large documents
in memory. Once in memory, however, the document can be easily and quickly read,
edited, and serialized. To search a single node, or to change an individual property, you
have to load the whole document in memory. As you can guess, this is not necessarily
an optimal approach and might not be the appropriate way to go for most applications.
Taking the cursor-like approach to its limit, you can also observe an interesting
convergence between readers and the XMLDOM. In fact, by visiting all element and
attribute nodes in the stream and storing in a memory tree the related data, you build a
dynamic and customized XMLDOM. Incidentally, this is just what happens in the .NET
Framework when XMLDOM classes are instantiated using readers to load data and are
serialized to disk using writers.
Readers vs. SAX
A SAX parser directly controls the evolution of the parsing process and pushes data to
the client application. A cursor parser (that is, an XML reader), on the other hand, plays
a more passive role and leaves client applications to control the process.
Giving applications, not the parser, control over the parsing process promotes the pull
To grasp the importance of XML writers, consider that, in general, the only alternative
you have for writing XML contents to any storage media consists of preparing the entire
output as a string and then writing it off. In this case, the markup nature of XML is more
hindrance than real help, because you must yourself take care of the intricacies of
quotation marks, attributes, indentation, and end tags.
In the .NET Framework, XML writers come to the rescue and let you write XML
documents programmatically in much the same way you write them through text
editors. For example, you can specify whether you want a namespace prefix, the
padding character and the size of the indentation, the quotation mark and the newline
character, and even how you want white spaces to be treated. To create nodes, you
simply use ad hoc methods to write comments, attributes, and element nodes. The
overall method of working is simple and extremely effective.
The .NET Framework provides several types of writers that use heterogeneous output
devices—strings, HTTP response, and HTML documents. You could also use an XML
text writer to dump contents to a stream object or a new text file. In the latter two cases,
you could also specify character encoding. If the encoding argument is null, the
Unicode 8-bits-per-character schema (UTF-8) will be used.
XML writers, and in particular the XmlTextWriter class, are used throughout the .NET
Framework for creating any sort of XML output. We'll look at XML writers in detail in
Chapter 4.
The XML Document Object API in .NET
As mentioned, along with XML readers and writers, the .NET Framework also provides
classes that load and edit XML documents according to the W3C DOM Level 1 and
Level 2 Core. The key XMLDOM class in the .NET Framework is XmlDocument—not
much different from the DOMDocument class, which you might recognize from working
with MSXML.
The XMLDOM supplies an in-memory tree-based representation of XML documents
and supports both navigation and editing of the document. In addition, the XMLDOM
classes can handle both XPath queries and XSLT.
Tightly coupled with the XmlDocument class is the XmlDataDocument class. It extends
queries must rely on the document in its entirety being held in memory and accessible
through a well-known interface—the XMLDOM.
The XSLT Processor
The key class for XSLT is XslTransform. The class works as an XSLT processor and
complies with version 1.0 of the XSLT recommendation. The class has two key
methods, Load and Transform, whose behavior is for the most part selfexplanatory.
Once you acquire an instance of the XslTransform class, you first load the source of an
XSL document that contains the transformation rules. By calling the Transform method,
you actually perform the conversion from native XML to the output format. Prior to
applying the transformation, the underlying XML document is loaded as a kind of
XMLDOM tree. (The details of XSLT are covered in Chapter 7.)
19
The XPath Query Engine
XPath is a language that allows you to navigate within XML documents. Think of XPath
as a general-purpose query language for addressing, sorting, and filtering both the
elements and the text of an XML document.
The XPath notation is basically declarative. Any XPath expression is a path within the
XML document that identifies the information with the given characteristics. The path
defines a pattern, and the resulting selection includes all the nodes that match it. The
selection is expressed through a notation that emphasizes the hierarchical relationship
between the nodes. It works in much the same way files and folders work. For example,
the XPath expression "book/publisher" means find the "publisher" element within the
"book" element. The XPath navigation model works in the context of a hierarchy of
nodes in the XML document's tree. XPath makes use of a variation of the
XmlDocument class, named XPathDocument.
Running an XPath query is not actually different from executing a TransactSQL (T-
SQL) query on SQL Server. Instead of getting back a collection of rows, a valid XPath
expression returns a collection of nodes. To scroll the returned nodes, you just use an
XPath-customized version of a reader. We'll look at XPath in more detail in Chapter 6.
approved standard—DOM Level 2 Core—is available at http://www.w3.org/TR/DOM-
Level-2.
Relevant information about XML standards is available from the W3C Web site, at
http://www.w3.org. If you want to learn more about the SAX specification, look at the
new Web site for the SAX project, at http://www.saxproject.org
.
20
A lot of useful developer-oriented documentation about XML is available on the Web
sites of the companies that support XML. In addition to the Microsoft Web site
(http://msdn.microsoft.com/xml), check out the Intel Developer Services Web site
(http://cedar.intel.com). In particular, you'll find an essential guide to XML in the .NET
Framework: http://cedar.intel.com/media/pdf/dotnet/net_jumpstart.pdf.
Finally, if you just want a good, all-encompassing book about XML programming, I
heartily recommend the Microsoft Press Core Reference book XML Programming
(http://www.microsoft.com/mspress/books/4798.asp), by R. Allen Wyke, Sultan
Rehman, and Brad Leupen (Microsoft Press, 2002). For a more general look into XML
as a unifying technology, Essential XML: Beyond Markup (Addison Wesley, 2000), by
Don Box, Aaron Skonnard, and John Lam, is still one of the best books available.