XSD Validation is where you check the syntax of a DOM-tree against an XML Schema Definition, which is a grammar of the expected XML elements and attributes.
An XML Schema Definition is always specified as an external file. It is typically shared by many XML documents. It must be referenced from attributes in the root element of the XML document (see below).
XSD has certain advantages and disadvantages over DTD for expressing XML grammars:
XSD offers more expressive grammar rules for elements and attributes, with a finer degree of filtering than DTD;
XSD cannot expand Entity References, for which you will still need DTD;
XSD is also legal XML syntax, but conventionally is stored in files with the extension ".xsd";
XSD may define the grammar for more than one DOM-tree, so validation must first find the rule for the DOM-tree's root element.
XSD Validation is enabled simply by setting the validation-level of the XMLReader to SCHEMA before you read in the XML file (see below). The XML file must reference a valid XML Schema.
Document validation is controlled through the values of an enumerated type Validation:
Validation.IGNORE - is the default setting. This turns off all entity reference expansion, DTD validation and XSD validation.
Validation.EXPAND - is the lowest setting, which reads DTDs only in order to expand entity references.
Validation.DOCTYPE - is the middle setting, which expands entity references and checks the XML document against a Doctype.
Validation.SCHEMA - is the highest setting, which expands entity references and checks the XML document against an XML Schema.
Validation is found in the package:
uk.ac.sheffield.jast.valid
Reading a XSD is handled internally - you don't have to request this explicitly; but for interest, XSDReader is used to read external XSDs. It has four main constructors:
XSDReader(File file, String encoding)
XSDReader(URL url, String encoding)
XSDReader(InputStream stream,
String encoding)
XSDReader(Reader reader,
String encoding)
These allow you to read from different kinds of source (from a file, from a web URL, or from another stream). They all require the character encoding (e.g. "UTF-8") as a String.
Since an XSD file is also a legal XML file, you may also read it using XMLReader and manipulate its DOM-tree like any other XML file.
XSDReader is a more specialised reader that also compiles the schema into grammar rules and returns an XMLSchema, which is a specialised kind of Document.
XSDReader is in the package:
uk.ac.sheffield.jast.valid
Validating a local XML file is easily done using the following Java code.
File file =
new File("my/xml/input.xml");
XMLReader reader =
new XMLReader(file, "UTF-8");
reader.setValidation(Validation.SCHEMA);
Document document =
reader.readDocument();
reader.close();
When XMLReader reads an XML file that refers to an XML Schema declaration, by default it stores the reference just as a text attribute (to save processing). However,
if SCHEMA Validation is requested, the reference is resolved to an XSD file, which is read by XSDReader;
the resulting XML Schema text is parsed and compiled into grammar rules;
and then the whole DOM-tree is checked against the compiled grammar, starting with the rule for the root element.
If there is no rule for the DOM-tree root, or if the grammar detects any XML faults, these faults are reported by raising a SemanticError. Otherwise, the check passes silently.
Validating XML read from a URL on the web is also easily done using the following Java code:
URL url = new URL(
"https://www.my.site/input.xml");
XMLReader reader =
new XMLReader(url, "ISO-8859-1");
reader.setValidation(Validation.SCHEMA);
Document document =
reader.readDocument();
reader.close();
This shows that you can specify a different character encoding Latin-1, which used to be the standard for the HTTP protocol (maybe UTF-8 now).
Once the DOM-tree has been read, it will then be validated against whatever XML Schema was referenced in the XML data.
An XML file must refer to its XML Schema, stored in a separate XSD file, via certain attributes of the root element. In the following, we assume an XML file Catalogue.xml with a root element called Catalogue; and that a schema lives in the /xsd subdirectory relative to the file.
The simplest way to refer to an XSD file is the option that declares no namespace, but only the local location of the schema:
<Catalogue
xmlns:xsi=
"https://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation=
"xsd/Catalogue.xsd">
...
</Catalogue>
This requires the two attributes:
xmlns:xsi - to declare the location of the formal definition of the XML Schema standard;
xsi:noNamespaceSchemaLocation - to declare the relative path to the local XSD file.
A slightly longer way to refer to an XSD file also declares a default XML namespace for the project:
<Catalogue
xmlns = "https://www.project.org/"
xmlns:xsi=
"https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"https://www.project.org/ xsd/Catalogue.xsd">
...
</Catalogue>
This requires the three attributes:
xmlns - to declare a default namespace URI for the Catalogue project.
xmlns:xsi - to declare the location of the formal definition of the XML Schema standard;
xsi:schemaLocation - has a space-separated string, consisting of namespace and path.
In this format, all XML elements defined within the file Catalogue.xml, including the schema file Catalogue.xsd, are declared to come from the same project namespace.
We show an example XML Schema Definition below. This is stored in the file Catalogue.xsd and will be referenced from any XML file using this grammar:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="https://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xs:element name="Catalogue">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="Film" type="showType"/>
<xs:element name="TVShow" type="showType"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:complexType name="showType">
<xs:sequence>
<xs:element name="Title" type="xs:string"/>
<xs:element name="Director" type="xs:string"/>
</xs:sequence>
<xs:attribute name="date" use="required" type="xs:integer"/>
<xs:attribute name="rating" use="implied" type="ratingType"/>
</xs:complexType>
<xs:simpleType name="ratingType">
<xs:restriction base="xs:string">
<xs:enumeration value="U"/>
<xs:enumeration value="PG"/>
<xs:enumeration value="12"/>
<xs:enumeration value="15"/>
<xs:enumeration value="18"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
This defines the grammar of the Catalogue root element in a related XML file. This XSD makes use of XML namespaces:
the root element is called xs:schema, consisting of a prefix xs and the name schema.
the root element declares the official W3C Schools XML namespace URL for XSD.
the root element also declares that all contents must be qualified by a namespace prefix.
The grammar defined in this XSD expresses the following rules:
Catalogue - the root element may contain an unbounded repetition of the choice of Film or TVShow elements, and these are of the type ShowType;
ShowType - is a type of element containing a sequence of Title and Director elements, and these are of the string-type (contain text);
ShowType is also a type of element containing the required attribute date, of the integer type, and the optional attribute rating, of the specified ratingType.
ratingType is a simple type, based on the string type, but restricted to the given set of values: "U, PG, 12, 15, 18".
The above is just one style of presenting an XML Schema Definition. The three common styles are called:
Russian Doll - in which every element is defined along with its type and attributes as a child of its parent element, in nested fashion;
Salami Slicer - in which every element is defined globally at the top-level as a child of schema, but their types refer back to earlier elements;
Venetian Blind - in which elements are defined separately from their types, only the root element is global and others are linked to their types.
Please refer to the Oracle XML Schema Design Patterns tutorial.
The XMLSchema node can be accessed in your programs, by using XSDReader to read and compile the XSD file, returning the XMLSchema instance.
The checking methods of XMLSchema may also be called explicitly in programs. There are four checking methods, which accept either a whole Document or the root Element of a DOM-tree as argument:
public boolean accept(Document doc);
public boolean accept(Element root);
public void validate(Document doc);
public void validate(Element root);
The accept() methods return true, if the DOM-tree is valid, or false otherwise. The validate() methods succeed silently if the DOM-tree is valid, or raise exceptions otherwise.
XMLSchema is found in the package:
uk.ac.sheffield.jast.xml
It is possible to visualise the grammar compiled by an XMLSchema. Every top-level ElementRule in the grammar is capable of writing a pretty-printed representation of itself, using a toString() method. This will print out one production from the grammar.
To see the whole grammar, call the access method getProductions() on the top-level rule, and this will return a list of all the productions in the grammar. You can iterate through the list and print out each rule as a production in BNF format:
XMLSchema schema = ... // you fetch
ElementRule topRule =
schema.getGrammar("Catalogue");
for (ElementRule rule :
topRule.getProductions()) {
System.out.println(rule);
}
JAST accepts XML schemas written in a variety of styles, and containing a wide range of W3C XSD constructions.
It accepts any of the Russian Doll, Salami Slice or Venetian Blind styles for presenting a schema and also handles mixtures of these styles.
It supports simple types, complex types, groups, attributes and attribute groups.
It supports sequence, choice, all and any (element) specifiers.
It supports the iterative constructs minOccurs and maxOccurs.
It supports extension and restriction of simple content and complex content.
The anyAttribute construction is not supported.
The W3C XSD type system is implemented in terms of filters that can be used to constrain the values of attributes or elements.
All IEEE numerical types are supported.
Most XSD basic types are supported (except for NOTATION and base64binary).
XSD simple types are typically one of these basic types, or a restriction on one of these types, expressed either as an enumeration, a regular expression, or a numerical subrange.
Both subranges and field-widths may be specified.
Please refer to the W3C Tutorial on XSD for more information about the XSD type system.
Please see the Javadoc documentation for more information on JAST filters.