XmlReader


The XmlReader class is an abstract class that allows you to specify an uncached, forward-only access to XML data. Similar to the way the XmlWriter class utilizes the XmlWriterSettings class, the style in which the XML document is read is controlled by the XmlReaderSettings class. The XmlReaderSettings class, which is new to .NET 2.0, allows you to configure the behavior of the XmlReader object before you even instantiate it.

For an example of this, try reading some XML from a file on disk. Use one of the previously presented XML files, as shown in Listing 15-15.

Listing 15-15: The MyXml.xml file that the XmlReader will utilize

image from book
      <?xml version="1.0" encoding="utf-8"?>      <MultiStockOrder>        <StockOrderMultiple>          <StockOrder>            <Symbol>MSFT</Symbol>            <Quantity>100</Quantity>            <OrderTime>2005-10-04</OrderTime>          </StockOrder>          <StockOrder>             <Symbol>INTC</Symbol>            <Quantity>110</Quantity>            <OrderTime>2005-10-04</OrderTime>          </StockOrder>          <StockOrder>            <Symbol>RTRSY</Symbol>            <Quantity>200</Quantity>            <OrderTime>2005-10-04</OrderTime>          </StockOrder>         </StockOrderMultiple>      </MultiStockOrder> 
image from book

With the XML file in place, the next step is to build a console application that can read through this XML document and work with some of the elements and their values. This is illustrated in Listing 15-16.

Listing 15-16: Using the XmlReader object to read the MyXml.xml file

image from book
      using System;      using System.Collections.Generic;      using System.Text;      using System.Xml;      using System.IO;      namespace XmlProject      {          class Program          {              static void Main(string[] args)              {                  try                  {                     XmlReaderSettings settings = new XmlReaderSettings();                     settings.IgnoreWhitespace = true;                     settings.IgnoreComments = true;                     settings.CheckCharacters = true;                     FileStream myStockOrders = new                        FileStream("C:/MyXml.xml", FileMode.Open);                     XmlReader xr = XmlReader.Create(myStockOrders, settings);                     while (xr.Read())                     {                         if (xr.NodeType == XmlNodeType.Element &&                             "Symbol" == xr.LocalName)                         {                             Console.WriteLine(xr.Name + " " +                               xr.ReadElementContentAsString());                         }                      }                     xr.Close();                     Console.WriteLine("Done");                     Console.ReadLine();                  }                  catch (System.Exception ex)                  {                     Console.Error.WriteLine(ex.ToString());                     Console.ReadLine();                  }              }          }      } 
image from book

As you review this bit of code, note that the first step is to instantiate the XmlReaderSettings class and assign it some values. In this case, the IgnoreWhitespace, IgnoreComment, and the CheckCharacters properties are set. After the XmlReaderSettings instance is ready to go, the next step is to retrieve the XML file through the use of the FileStream object and assign both the XML document and the settings applied through the XmlReaderSettings object to the XmlReader object (xr).

The Read() method of the XmlReader reads true if there is anything to be read in the document, including whitespace, comments, and similar items. This is why these items are set to be ignored through the XmlReaderSettings instance in the program. Because of this, a check is done on the element being read to determine if it is an XML element using the NodeType property, and then a second check is done to see if the element has the name Symbol by comparing it to the LocalName property.

      if (xr.NodeType == XmlNodeType.Element && "Symbol" == xr.LocalName)      {          // Code removed for clarity      } 

After the element is found, its name (it will be Symbol if it passed the check) and the value of the element are then written to the console.

      Console.WriteLine(xr.Name + " " + xr.ReadElementContentAsString()); 

In this case, the name of the element is retrieved through the Name property, and the value of the element is retrieved through the ReadElementContentAsString method. In addition to the ReadElementContentAsString method, you can use many other data types as well (this is also explained in more detail shortly).

Once run, the console application produces the results illustrated in Figure 15-10.

image from book
Figure 15-10

Reading XML with a Schema Validation

One problem with the XML reading example from the previous section is that the code can process any XML document, and if that document contains a <Symbol> element somewhere in its contents, then the node's name and value are used by the console application. This is a problem because you are really interested in processing only XML documents for stock orders that follow the MyXml.xml document pattern. This is why working with XML schemas is such a powerful tool.

The nice thing with the XmlReader object is that you can provide an XSD schema to be applied to an inputted document through the XmlReaderSettings class. Listing 15-17 shows an example of this validation check on the retrieved XML document.

Listing 15-17: Performing schema validations with the XmlReader instance

image from book
      using System;      using System.Collections.Generic;      using System.Text;      using System.Xml;      using System.Xml.Schema;      using System.IO;      namespace XmlProject      {          class Program          {              static void Main(string[] args)              {                  try                  {                     XmlSchemaSet mySchema = new XmlSchemaSet();                     mySchema.Add(null, "C:/MyXml.xsd");                     XmlReaderSettings settings = new XmlReaderSettings();                     settings.IgnoreWhitespace = true;                     settings.IgnoreComments = true;                     settings.CheckCharacters = true;                     settings.Schemas.Add(mySchema);                     settings.ValidationType = ValidationType.Schema;                     settings.ValidationFlags =                        XmlSchemaValidationFlags.ReportValidationWarnings;                     settings.ValidationEventHandler += new                        ValidationEventHandler(settings_ValidationEventHandler);                     FileStream myStockOrders = new                         FileStream("C:/MyXml.xml", FileMode.Open);                     XmlReader xr = XmlReader.Create(myStockOrders, settings);                     while (xr.Read())                     {                         if (xr.NodeType == XmlNodeType.Element &&                             "Symbol" == xr.LocalName)                         {                             Console.WriteLine(xr.Name + " " +                               xr.ReadElementContentAsString());                         }                     }                     xr.Close();                     Console.WriteLine("Done");                     Console.ReadLine();                  }                  catch (System.Exception ex)                  {                     Console.Error.WriteLine(ex.ToString());                     Console.ReadLine();                  }              }      static void settings_ValidationEventHandler(object sender,                 ValidationEventArgs e)              {                  throw new Exception("Your XML is invalid.");              }          }      } 
image from book

As you look over the code, note that the first step is to import in the System.Xml.Schema namespace because you want to use the XmlSchemaSet class in your code. The XmlSchemaSet, which is a new class as of the .NET Framework 2.0, is an object to represent the XSD document that you want to validate the XML data to. The creation of the XmlSchemaSet instance is done using the Add method.

      XmlSchemaSet mySchema = new XmlSchemaSet();      mySchema.Add(null, "C:/MyXml.xsd"); 

Now that the schema you want to use is ready and in place, the next step is to add this instance to the XmlReaderSettings object that is created.

      settings.Schemas.Add(mySchema);      settings.ValidationType = ValidationType.Schema;      settings.ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings;      settings.ValidationEventHandler += new         ValidationEventHandler(settings_ValidationEventHandler); 

First off, the schema stored in the XmlSchemaSet is associated with the XmlReaderSettings instance by using the Schemas.Add method and passing in the XmlSchemaSet instance, mySchema. Next, you declare through the ValidationType property that you are specifying a schema. Other options include: Auto, DTD, None, and XDR. From there, you then specify through the ValidationFlags property that you are interested in reporting validation warnings, and then you simply make an association to a validation event handler to handle any validation errors that might occur. It is important to note that the Auto and XDR options of the ValidationType property are obsolete in the .NET Framework 2.0.

When you are running the console application against an XML document that doesn't follow the rules defined in the MyXml.xsd schema, you see something similar to what is illustrated in Figure 15-11.

image from book
Figure 15-11

Casting XML Types to .NET-Compliant Types

.NET CLR-compliant types are not 100% inline with XML types. For this reason, the .NET Framework 2.0 has introduced some new methods in the XmlReader that simplify the process of casting from one of these XML types to .NET types.

You saw an earlier example of this being done with one of the new classes. Using the ReadElementContentAs method, you can easily perform the required casting.

      string userName =         (string) myXmlReader.ReadElementContentAs(typeof(System.String), null);      DateTime myDate =         (DateTime) myXmlReader.ReadElementContentAs(typeof(System.DateTime), null); 

A whole series of direct casts through new classes are available:

  • q ReadElementContentAsBase64

  • q ReadElementContentAsBinHex

  • q ReadElementContentAsBoolean

  • q ReadElementContentAsDateTime

  • q ReadElementContentAsDecimal

  • q ReadElementContentAsDouble

  • q ReadElementContentAsFloat

  • q ReadElementContentAsInt

  • q ReadElementContentAsLong

  • q ReadElementContentAsObject

  • q ReadElementContentAsString

This makes it easy to perform operations like those shown in Listing 15-17:

      Console.WriteLine(xr.Name + " " + xr.ReadElementContentAsString()); 




Professional XML
Professional XML (Programmer to Programmer)
ISBN: 0471777773
EAN: 2147483647
Year: 2004
Pages: 215

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net