Programming with Schemas



Programming with Schemas

Programming with schemas can really be done at two different levels: using APIs within the .NET Framework for actually reading and writing XML Schema documents, and using APIs for manipulating XML that is matched to a specific XML schema. Of course, it's important to keep in mind that the XML Serialization technology (refer to Chapter 5) is also based on XML Schemas, and offers a pleasing alternative to using streams and validators.

Programming Schema-Based XML

When reading a stream of XML, you can verify that it is valid according to its schema by using the XmlValidatingReader class instead of the normal XmlTextReader. To do this, we basically construct an XmlTextReader as we normally would, but then construct an XmlValidatingReader from that, as shown in Listing 8.22.

Using the XmlValidatingReader Class
if( openFileDialog1.ShowDialog() == DialogResult.OK )
{
     filename = openFileDialog1.FileName;
     FileStream stream = new FileStream( filename , FileMode.Open);
     XmlTextReader treader = new XmlTextReader( stream );
     XmlValidatingReader reader = new XmlValidatingReader( treader );
     Validate(reader);
}

In the validate function, we'll add the schema object that represents schema for this XML, and then set a callback function to be called whenever a piece of XML doesn't validate:

void Validate( XmlValidatingReader reader) 
{
     reader.Schemas.Add( schema );
     reader.ValidationType = ValidationType.Schema;
     reader.ValidationEventHandler +=
               new ValidationEventHandler (ValidationCallBack);
     while( reader.Read() ){}
}

public void ValidationCallBack (
                       object sender,
                       ValidationEventArgs args)
{
     MessageBox.Show("Validation error: " + args.Message);
}

Manipulating XML Schema Documents

There is set of classes in the System.Xml.Schema namespaces designed specifically for reading and writing XML schema documents. For example, it is possible to build a Windows application that reads in a schema and outputs a tree of the elements and types defined in the schema document. This application could end up looking something like Figure.

3. Tree View of an XML Schema

graphics/08fig03.gif

To build this application, we would first need to query the user for the filename of the XML schema document, and then load it into an XmlSchema object:

DialogResult dr = openFileDialog1.ShowDialog(); 
if( DialogResult.OK == dr )
{
    String filename = openFileDialog1.FileName;
    FileStream filestream = new FileStream( filename, FileMode.Open );
    XmlSchema schema = XmlSchema.Read( filestream, null );
}

Now, assuming that there is a TreeView control called treeView1, we can write code to loop through the items within the schema object, and then display their information. To start with, we can loop through the collection of items found within the schema:

foreach( Object o in schema.Items ) 

Next, we can check the type of the item, to see if it is an element, attribute, complex type, or simple type:

if( o.GetType() == typeof( XmlSchemaAttributeGroup ) ) 
{
     //do something
}
else if( o.GetType() == typeof( XmlSchemaElement ) )
{
     //do something
}
else if( o.GetType() == typeof( XmlSchemaComplexType) )
{
     //do something
}
else if(t.ContentModel.GetType()==typeof(XmlSchemaSimpleContent))
{
     //do something
}

Now, within each of the if blocks, we also can examine further information about these particles. I'll take the XmlSchemaElement block as an example. Here, we create a tree node that gives us the name of the element and another child node of that, which gives us the type:

else if( o.GetType() == typeof( XmlSchemaElement ) ) 
{
     XmlSchemaElement e = (XmlSchemaElement)o;
     TreeNode node = new TreeNode( e.Name );
     TreeNode n = new TreeNode( "Type: " + e.SchemaTypeName.Name );
     node.Nodes.Add( n );
     elementNode.Nodes.Add( node );
}

NOTE

Many of the classes in the .NET Framework are built on top of other classes. For example, the XmlSchema class—along with most of the other classes in the System.Xml.Schema namespaces—was built using the XML Serialization technology.