Validation with XMLBeans

An essential part of schema-related work is validating instances based on the schema. XMLBeans provides a number of ways for you to ensure your instances are valid, both at the command line and programmatically at run time.

Validation, XMLBeans-Style

XMLBeans' schema-oriented approach to handling XML makes validation an important part of its work. However, XMLBeans has a specific approach to validation that's helpful to keep in mind when you're working.

Validation features include the following:

XMLBeans Validates Only When You Ask It To — Generally

Given XMLBeans' focus on schema-oriented work, it's natural to assume that it might check up on you as your code is making changes to an instance — that it might prevent your code from doing something that would render the instance invalid along the way. But, by default, it doesn't. The design of XMLBeans assumes that an XML instance might go through multiple invalid states before changes are complete. As a result, generally speaking, XMLBeans keeps quiet while changes are occurring.

Note: The exception to this rule is that XMLBeans validates your schema when you're compiling it using scomp or the xmlbean Ant task.

XMLBeans Does Not Validate an Instance While Parsing It

But it's not hard to get the impression that it does. For example, imagine that you're parsing an XML instance using a statement such as the following:

MyXmlSchemaType myXmlBean = MyXmlSchemaType.Factory.parse(myXml);

If the namespace declared in the myXml instance doesn't match the target namespace of the schema from which MyXmlSchemaType was generated, parsing will fail with an error message. Likewise, you'll get messages for other mismatches between the shape of myXml and the XML shape described by the schema.

But these failures and messages don't result from validation. Instead, all XMLBeans is doing is a not-very-deep check to see if the instance shouldn't be bound to the XMLBeans type generated from schema. In other words, the checking done at the parsing stage is simply a "low bar" effort to avoid trouble down the road.

Validation, on the other hand, is designed to verify that the instance conforms completely to the schema.

So you can validate in any of three ways:

Tools for Validating

XMLBeans tools for validation include command-line tools and APIs.

Command-line Tools for Validation

Among the many command-line tools XMLBeans provides, you'll find two that are specifically for validation.

APIs for Validation

XMLBeans APIs provide ways for you to validate on request — say, after your code has finished editing an instance and before it passes the instance elsewhere. You can also specify that your calls to set* methods should validate on-the-fly the instance that is being edited; you do this as an option when your code creates the XMLBeans schema type instance.

Validation When You Ask for It

Both the validate methods described here are available from any XMLBeans type generated from schema during schema compilation (because all such types inherit from XmlObject). Both methods are designed to validate the instance that is bound to the type from which the method is called. For example, if your schema defines a <purchase-order> element with <item> children, calling the myItem.validate() method will validate the <item> instance bound to Item. This includes the <item> element's children, but not the <purchase-order> element or the <item> element's siblings.

Both methods return a boolean to indicate validity, and one of the methods lets you specify options for validation, such as capturing messages about why an invalid instance is invalid.

Also, see the section on validating as you go for information about using the XmlOptions.setValidateOnSet method.

Retrieving Error Messages About Invalid XML

When you'll be validating with one of the validate methods, you can specify a java.util.Collection implementation as an error listener. As validation occurs, errors are added to the listener. After validation (and if the instance is found to be invalid) you can examine the errors. Here's an example:

// Set up the validation error listener.
ArrayList validationErrors = new ArrayList();
XmlOptions validationOptions = new XmlOptions();
validationOptions.setErrorListener(validationErrors);

MyDocument myDoc = MyDocument.Factory.parse(pathToXml);

// Do some editing to myDoc.

// During validation, errors are added to the ArrayList for
// retrieval and printing by the printErrors method.
boolean isValid = myDoc.validate(validationOptions);

// Print the errors if the XML is invalid.
if (!isValid)
{
    Iterator iter = validationErrors.iterator();
    while (iter.hasNext())
    {
        System.out.println(">> " + iter.next() + "\n");
    }
}

Validation As You Go

By default, an XML instance will not be validated at run time as your code makes changes. However, you can change this behavior for limited on-the-fly validation. To do this, you specify the "validate on set" option when you create the XMLBeans type instance — you do this with the XmlOptions.setValidateOnSet method.

When you specify this option, XMLBeans with throw an exception when your code invalidates the XML through a set* method. Note that you can't specify an error listener for use in conjunction with this means of validating. Also, with "validate on set," only simple schema types will be validated. Schema types not validated by this approach include, for example, those defining elements with attributes or elements with children.

Because its functionality is limited to simple schema types and it validates for set* method calls, you should regard this validation approach as a debugging tool, rather than an alternative to using a validate method. For example, you might use it to determine which errant bit of code is creating an invalid chunk of XML.

Note: This sort of validation is not supported during changes you make using an XmlCursor instance.

Among the methods you can use to create an XMLBeans instance — the parse methods and the newInstance method — you'll find versions that take an XmlOptions instance as a parameter. Specifying this option would look something like the following:

XmlOptions validateOptions = new XmlOptions();

// Tell XMLBeans you want to validate on the fly.
validateOptions.setValidateOnSet();
// Create the new instance, specifying the option.
PurchaseOrder newPo = PurchaseOrder.Factory.newInstance(validateOptions);

// ... Code to edit the instance via get and set methods ... 

Related Topics

Getting Started with XMLBeans