Tải bản đầy đủ - 0 (trang)
6-8. Validate an XML Document Against a Schema

6-8. Validate an XML Document Against a Schema

Tải bản đầy đủ - 0trang

CHAPTER 6 ■ XML PROCESSING



tag, if order is important, or an tag if it is not. Here is how you might model the

element in the product catalog. Notice that attributes are always declared after elements, and

they are not grouped with a or tag because order is never important:

















By default, a listed element can occur exactly one time in a document. You can configure this

behavior by specifying the maxOccurs and minOccurs attributes. Here is an example that allows an

unlimited number of products in the catalog:



Here is the complete schema for the product catalog XML:












































maxOccurs="unbounded" />









282



www.it-ebooks.info



CHAPTER 6 ■ XML PROCESSING











The XmlReader class can enforce these schema rules, providing you explicitly request a validating

reader when you use the XmlReader.Create method. (Even if you do not use a validating reader, an

exception will be thrown if the reader discovers XML that is not well formed, such as an illegal character,

improperly nested tags, and so on.)

Once you have created your validating reader, the validation occurs automatically as you read

through the document. As soon as an error is found, the XmlReader raises a ValidationEventHandler

event with information about the error on the XmlReaderSettings object given at creation time. If you

want, you can handle this event and continue processing the document to find more errors. If you do

not handle this event, an XmlException will be raised when the first error is encountered, and processing

will be aborted.



The Code

The next example shows a utility class that displays all errors in an XML document when the ValidateXml

method is called. Errors are displayed in a console window, and a final Boolean variable is returned to

indicate the success or failure of the entire validation operation.

using System;

using System.Xml;

using System.Xml.Schema;

namespace Apress.VisualCSharpRecipes.Chapter06

{

public class ConsoleValidator

{

// Set to true if at least one error exists.

private bool failed;

public bool Failed

{

get {return failed;}

}

public bool ValidateXml(string xmlFilename, string schemaFilename)

{

// Set the type of validation.

XmlReaderSettings settings = new XmlReaderSettings();

settings.ValidationType = ValidationType.Schema;

// Load the schema file.

XmlSchemaSet schemas = new XmlSchemaSet();

settings.Schemas = schemas;

// When loading the schema, specify the namespace it validates

// and the location of the file. Use null to use



283



www.it-ebooks.info



CHAPTER 6 ■ XML PROCESSING



// the targetNamespace value from the schema.

schemas.Add(null, schemaFilename);

// Specify an event handler for validation errors.

settings.ValidationEventHandler += ValidationEventHandler;

// Create the validating reader.

XmlReader validator = XmlReader.Create(xmlFilename, settings);

failed = false;

try

{

// Read all XML data.

while (validator.Read()) {}

}

catch (XmlException err)

{

// This happens if the XML document includes illegal characters

// or tags that aren't properly nested or closed.

Console.WriteLine("A critical XML error has occurred.");

Console.WriteLine(err.Message);

failed = true;

}

finally

{

validator.Close();

}

return !failed;

}

private void ValidationEventHandler(object sender,

ValidationEventArgs args)

{

failed = true;

// Display the validation error.

Console.WriteLine("Validation error: " + args.Message);

Console.WriteLine();

}

}

}

Here is how you would use the class to validate the product catalog:

public class Recipe06_08

{

private static void Main()

{

ConsoleValidator consoleValidator = new ConsoleValidator();

Console.WriteLine("Validating ProductCatalog.xml.");



284



www.it-ebooks.info



CHAPTER 6 ■ XML PROCESSING



bool success = consoleValidator.ValidateXml(@"..\..\ProductCatalog.xml",

@"..\..\ProductCatalog.xsd");

if (!success)

Console.WriteLine("Validation failed.");

else

Console.WriteLine("Validation succeeded.");

Console.ReadLine();

}

}

If the document is valid, no messages will appear, and the success variable will be set to true. But

consider what happens if you use a document that breaks schema rules, such as the

ProductCatalog_Invalid.xml file shown here:





Acme Fall 2003 Catalog

Jan 1, 2004





Magic Ring

$342.10

true





Flying Carpet

982.99

Yes







If you attempt to validate this document, the success variable will be set to false, and the output

will indicate each error:

Validating ProductCatalog_Invalid.xml.



Validation error: The 'expiryDate' element has an invalid value according to

its data type. [path information truncated]



Validation error: The 'productPrice' element has an invalid value according to



285



www.it-ebooks.info



CHAPTER 6 ■ XML PROCESSING



its data type. [path information truncated]



Validation error: The 'inStock' element has an invalid value according to its

data type. [path information truncated]



Validation failed.

Finally, if you want to validate an XML document and load it into an in-memory XmlDocument, you

need to take a slightly different approach. The XmlDocument provides its own Schemas property, along with

a Validate method that checks the entire document in one step. When you call Validate, you supply a

delegate that points to your validation event handler.

Here is how it works:

XmlDocument doc = new XmlDocument();

doc.Load(@"..\..\Product_Catalog.xml");

// Specify the schema information.

XmlSchemaSet schemas = new XmlSchemaSet();

schemas.Add(null, @"..\..\ProductCatalog.xsd");

doc.Schemas = schemas;

// Validate the document.

doc.Validate(new ValidationEventHandler(ValidationEventHandler));



6-9. Use XML Serialization with Custom Objects

Problem

You need to use XML as a serialization format. However, you don’t want to process the XML directly in

your code—instead, you want to interact with the data using custom objects.



Solution

Use the System.Xml.Serialization.XmlSerializer class to transfer data from your object to XML, and

vice versa. You can also mark up your class code with attributes to customize its XML representation.



286



www.it-ebooks.info



CHAPTER 6 ■ XML PROCESSING



How It Works

The XmlSerializer class allows you to convert objects to XML data, and vice versa. This process is used

natively by web services and provides a customizable serialization mechanism that does not require a

single line of custom code. The XmlSerializer class is even intelligent enough to correctly create arrays

when it finds nested elements.

The only requirements for using XmlSerializer are as follows:





The XmlSerializer serializes only properties and public variables.







The classes you want to serialize must include a default zero-argument

constructor. The XmlSerializer uses this constructor when creating the new

object during deserialization.







All class properties must be readable and writable. This is because XmlSerializer

uses the property get accessor to retrieve information and the property set

accessor to restore the data after deserialization.



■ Note You can also store your objects in an XML-based format using .NET serialization and System.Runtime.

Serialization.Formatters.Soap.SoapFormatter. In this case, you simply need to make your class

serializable—you do not need to provide a default constructor or ensure all properties are writable. However, this

gives you no control over the format of the serialized XML.



To use XML serialization, you must first mark up your data objects with attributes that indicate the

desired XML mapping. You can find these attributes in the System.Xml.Serialization namespace and

include the following:





XmlRoot specifies the name of the root element of the XML file. By default,

XmlSerializer will use the name of the class. You can apply this attribute to the

class declaration.







XmlElement indicates the element name to use for a property or public variable. By

default, XmlSerializer will use the name of the property or public variable.







XmlAttribute indicates that a property or public variable should be serialized as an

attribute, not an element, and specifies the attribute name.







XmlEnum configures the text that should be used when serializing enumerated

values. If you don’t use XmlEnum, the name of the enumerated constant will be

used.







XmlIgnore indicates that a property or public variable should not be serialized.



287



www.it-ebooks.info



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

6-8. Validate an XML Document Against a Schema

Tải bản đầy đủ ngay(0 tr)

×