.NET Parsing with Validation in .NET with XmlValidatingReader

The XmlTextReader covered in the previous section is an extremely fast and efficient parser, but it does have the downside of not doing any validation of the XML document. The .NET XML architecture provides a higher-level parser called XmlValidatingReader that provides this functionality. We will investigate the XmlValidatingReader in this section and use it to create an example that checks the validity of a document using a DTD.

The XmlValidatingReader doesn't parse text directly. Instead, it relies on another XmlReader like XmlTextReader for that lower-level functionality. Because we've just covered the XmlTextReader in the last section, that is the parser we'll use for our example. Therefore, first a standard XmlTextReader is constructed.

XmlTextReader xmlTextReader = new XmlTextReader("example.xml"); 

Next, we create an XmlValidatingReader. Instead of passing the name of the file to be parsed into the XmlValidatingReader constructor, the XmlTextReader that will actually do the text parsing is passed into the constructor.

xmlValidatingReader xmlValidatingReader = new XmlValidatingReader(xmlTextReader); 

Now we're ready to tell the XmlValidatingReader what type of validation we want to have done to the document. This is done by setting the ValidationType property of the XmlValidatingReader to the desired validation type. The XmlValidatingReader supports five types of validation:

  • DTD— Validate the Document according to DTD.

  • None— Do Not Validate the Document.

  • Schema— Use an XSD schema to validate the document.

  • XDR— Validate against an XML-Data Reduced Schema.

  • Auto— Attempt to determine from the document what type of validation to use.

Note

In addition to supporting the W3C XSD schema standard, the Microsoft XML Data Reduced (XDR) schema standard is supported. The XDR schema standard is based on early W3C work on schemas. Although it is similar to XSD schemas, it is not compatible.


For our example, we will validate our document against a DTD.

xmlValidatingReader.ValidationType = ValidationType.DTD; 

Handling Validation Errors

Validation handling is done with an event-based architecture, similar to SAX. The document is still parsed on demand as it was with the XmlTextReader. However, in order to receive notification that a validation error has occurred, a callback must be registered with the XmlValidatingReader. This is done by first generating a helper class that will be used to construct the callback. Because events are used to signal validation, a Boolean variable called success will be added to the class to keep track of whether a validation error has occurred:

class ValidationHelper 
{
  public bool success = true;
}

Now we're ready to add the event handler. Under .NET, an event callback is called a delegate and is constructed from a reference to a method in a class. Therefore, a method to be called whenever a validation event needs to be added. This method takes two arguments.

  • First, an object is passed to the handler containing the object that sent the event.

  • Second, a ValidationEventArgs object is passed with information on the validation event that triggered the call. The ValidationEventArgs object contains a string property called message that includes the relevant validation error.

For this example, the event handler will signal that an error has occurred by writing the error message to the console. Finally, the event handler sets the success variable to false so that it can be checked later.

public void ValidationCallBack (object sender, ValidationEventArgs args) 
{
  Console.WriteLine("Validation error:");
  Console.WriteLine(args.Message);
  Console.WriteLine();
  success = false;
}

Now that the validation handler has been constructed, it needs to be registered in the main program. This is done in .NET by constructing a ValidationEventHandler object that refers to the method that is to be called. First, an instance of the ValidationHelper class is created. Then a reference to the ValidationCallBack method is added to the list of handlers to be called by the XmlValidatingReader whenever a validation error occurs:

ValidationHelper validationHelper = new ValidationHelper(); 
xmlValidatingReader.ValidationEventHandler += new ValidationEventHandler
 (validationHelper.ValidationCallBack);

Validating the Document

Now that the mechanism for reporting errors has been put in place, we can go ahead and start parsing the document. This is done using the same method as the XmlTextReader: calling the Read method of the XmlValidatingReader object until there are no remaining nodes. In this case, we are only interested in validation, so a while loop is used to cycle over every node without acting on any of the nodes. This will work because validation errors are signaled as events to the ValidationEventHandler.

while ( xmlValidatingReader.Read() )  {    } 

Now that the entire document has been parsed, we want to report back to the user whether validation was successful. Because we have a reference to the ValidationHelper object, all that needs to be done is to check the Boolean success variable inside that object and use it to report whether validation was successful or unsuccessful.

if (validationHelper.success == true) 
  Console.WriteLine("Validation was successful");
else
  Console.WriteLine("Validation was unsuccessful");

The full C# code to this example is shown in Listing 17.4, and the equivalent Visual Basic .NET code is shown in Listing 17.5. If the sample document at the beginning of the chapter is used with this example, "Validation was successful" is reported. However, if we modify the example slightly to be invalid, as shown in Listing 17.6, the following validation errors are reported:

Validation error: 
The required attribute 'href' is missing. An error occurred at file:
file://src/XmlValidatingReader/bin/Debug/example2.xml(18, 4).

Validation error:
Element 'parsers' has invalid content. Expected 'parser'. An error occurred at
file:file://src/XmlValidatingReader/bin/Debug/example2.xml(25, 4).

Validation error:
The 'extra' element is not declared. An error occurred at
file://src/XmlValidatingReader/bin/Debug/example2.xml(25, 4).

Validation was unsuccessful
							

Listing 17.4. Validating Example in C#
using System;
using System.Xml;
using System.Text;
using System.Xml.Schema;

namespace SimpleXmlValidatingReader
{
  class ValidationHelper
  {
    public bool success = true;
    public void ValidationCallBack (object sender, ValidationEventArgs args)
    {
      Console.WriteLine("Validation error:");
      Console.WriteLine(args.Message);
      Console.WriteLine();
      success = false;
    }
  }

  class SimpleXmlValidatingReader
  {
    static void Main(string[] args)
    {
      try
      {
        //Create an instance of the xmlValidatingReader.
        XmlTextReader xmlTextReader = new XmlTextReader("example2.xml");
        XmlValidatingReader xmlValidatingReader =
                      new XmlValidatingReader(xmlTextReader);
        xmlValidatingReader.ValidationType = ValidationType.DTD;

        // Add a validation handler to the Document
        ValidationHelper validationHelper = new ValidationHelper();
        xmlValidatingReader.ValidationEventHandler +=
                      new ValidationEventHandler (validationHelper.ValidationCallBack);
        // Read through the entire document
        while ( xmlValidatingReader.Read() )  {    }
        xmlValidatingReader.Close();

        // Report whether validation was successful
        if (validationHelper.success == true)
          Console.WriteLine("Validation was successful");
        else
          Console.WriteLine("Validation was unsuccessful");
      }
      catch (XmlException ex)
      {
        Console.WriteLine("An XML exception occurred: " + ex.ToString());
      }     
      catch (Exception ex)
      {
        Console.WriteLine("A general exception occurred: " + ex.ToString());
      } 
    }
  }
}
							

Listing 17.5. Validating Example in Visual Basic .NET
Imports System
Imports System.Xml
Imports System.Text
Imports System.Xml.Schema

Module XmlValidatingReaderVB

  Public Class ValidationHelper
    Public success As Boolean = True
    Public Sub ValidationCallBack(ByVal sender As Object, ByVal args As ValidationEventArgs)
      Console.WriteLine("Validation error:")
      Console.WriteLine(args.Message)
      Console.WriteLine()
      success = False
    End Sub
  End Class

  Public Class SimpleXmlValidatingReader
    Public Shared Sub Main()
      Try
        'Create an instance of the xmlValidatingReader.
        Dim xmlTextReader As XmlTextReader
        xmlTextReader = New XmlTextReader("example2.xml")

        Dim xmlValidatingReader As XmlValidatingReader
        xmlValidatingReader = New XmlValidatingReader(xmlTextReader)
        xmlValidatingReader.ValidationType = ValidationType.DTD


        ' Add a validation handler to the Document
        Dim validationHelper As ValidationHelper
        validationHelper = New ValidationHelper()
        AddHandler xmlValidatingReader.ValidationEventHandler, AddressOf validationHelper
.ValidationCallBack

        ' Read through the entire document
        While xmlValidatingReader.Read()
        End While
        xmlValidatingReader.Close()

        ' Report whether validation was successful
        If validationHelper.success = True Then
          Console.WriteLine("Validation was successful")
        Else
          Console.WriteLine("Validation was unsuccessful")
        End If
        Catch ex As XmlException
          Console.WriteLine("An XML exception occurred: " + ex.ToString())
        Catch ex As Exception
          Console.WriteLine("A general exception occurred: " + ex.ToString())
      End Try
    End Sub
  End Class
End Module

Listing 17.6. Sample Invalid Document
<?xml version="1.0" ?>
<!DOCTYPE net_xml [
  <!ELEMENT net_xml        (standards, parsers)>
  <!ELEMENT standards (standard)+>
  <!ELEMENT parsers (parser)+>
  <!ELEMENT parser (#PCDATA)>
  <!ELEMENT standard (#PCDATA)>
  <!ATTLIST parser
      href     CDATA    #REQUIRED
  >
  <!ATTLIST standard
      href     CDATA    #REQUIRED
  >
]>
<net_xml>
  <standards>
    <standard>.NET Standards Documents</standard>
    <standard href="http://www.w3.org/DOM/">Document Object Model(DOM)</standard>
    <standard href="http://www.saxproject.org/">Simple API for XML(SAX)</standard>
  </standards>
  <parsers>
    <parser href="">XmlTextReader</parser>
    <parser href="">XmlNodeReader</parser>
    <extra>bogus element</extra>
  </parsers>
</net_xml>
							

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.76.218