XML has become the lingua franca of information exchange. There is hardly a technology anymore that doesn’t use XML data in some way, whether it’s an import/export format, a native database format, or just configuration data.
This is due in part to its very nature. XML stands for eXtensible Markup Language, and it’s eminently flexible and suited to a wide variety of tasks.
.NET supports XML in many ways, from a multitude of ways to read, parse, and search, to creation and validation.
Most samples in this chapter use the System.XML
namespace.
Solution: Automatic object serialization is the easiest way to translate between XML and your binary objects. The biggest caveat is that it only works on public types and public data members in those types. Given that, let’s look at an example with some test classes:
Notice that nothing in here has anything to do with XML. These are just application data objects.
To serialize (and then deserialize), use code similar to the following:
Notice that the XmlSerializer
correctly handled the null
value of AddressLine2
.
Solution: Use of XmlSerializer
is a largely automated process, but there are some easy ways to modify the XML to fit your needs. For example, suppose you modify the Person
class with these attributes:
You get this output:
Although other attributes can give you more control, these three are the most common.
When creating XML from scratch, there are, in general, two methods you can use:
• Write out each element and attribute in order, from start to finish.
• Build up a document object model (DOM).
There are tradeoffs between these two methods. Basically, it’s between speed and efficiency in working with the data. Building up a DOM in memory allows you to easily work with any nodes, but it takes up a lot of resources and is slow. Just writing out the elements is very fast, but this can be harder for more complex data models. Examples of both are shown in this section.
XmlDocument
Solution: The XmlDocument
class is the in-memory version of XML’s node structure.
XmlWriter
Solution: Use an XmlWriter
. By doing so, you’re taking on the responsibility of figuring out the correct relationships among subnodes, the start and end of tags, and where attributes should go.
The tradeoffs inherent in generating an XML file with the two different methods exist even more obviously when reading one in. If the XML file is large and complex, using XmlDocument
could be painfully slow. On the other hand, using XmlTextReader
is very fast, but puts all the onus of tracking state on you. Only you can decide how to resolve these tradeoffs.
XmlDocument
Solution: The XmlDocument
class contains methods for loading XML from files, streams, or strings.
XmlTextReader
Solution: Use the XmlTextReader
class, which can read from a variety of sources. In this case, because the source XML is in a string, you need to use a StringReader
to convert it into a stream for the XmlTextReader
.
You can easily see how this method involves a bit more code. Again, it’s all about tradeoffs.
Once, while working on an application that read a few large XML files (3MB or so in my case) on startup, I gave the app an instant performance boost merely by switching from using XmlDocument
to XmlTextReader
.
Solution: XML documents can be validated in a number of ways, one common way being the use of XML schemas.
Suppose you have a schema file defined like this:
The following code will validate the XML snippet against the previous schema, assuming it was in the file XmlBookSchema.xsd:
Solution: In addition to reading XML the traditional way, via XmlDocument
or XmlTextReader
, you can use XPathDocument
and related classes to query XML using XPath, a query language defined for XML.
Here is our source XML file (LesMis.xml
):
This code will perform a query for all the chapter names:
Here is the output:
Solution: Using some of the knowledge you gained from the chapter on databases, you can grab a DataSet
, which has a nice WriteXml()
method.
If we run this on our sample table from the database chapter, we get the following:
Solution: This is done using XML Transforms, which .NET supports out of the box.
Using the earlier XML file with chapter headings from Les Misérables, let’s add another file, an XML transformation file that includes the HTML and XML template tags to insert the data (see Listing 14.1).
Here is some simple code to perform the transformation and display the resulting HTML file:
The results are displayed in Figure 14.1.