XML Configurations
An important sub category of hierarchical configurations files are XML
documents. Commons Configuration ships with the
XMLConfiguration
class that can read and write files of this
type. All features described in the chapter about
Hierarchical Configurations are
supported by XML configurations as well. In this chapter the additional
functionality offered by the XMLConfiguration
class is
discussed.
Validation of XML configuration files
XML parsers provide support for validation of XML documents to ensure that they
conform to a certain DTD or XML Schema. This feature can be useful for
configuration files, too. XMLConfiguration
allows this feature
to be enabled when files are loaded.
Validation using a DTD
The easiest way to turn on validation is to simply set the
validating
property to true in the
initialization parameters of the configuration builder as shown in
the following example:
Parameters params = new Parameters();
FileBasedConfigurationBuilder<XMLConfiguration> builder =
new FileBasedConfigurationBuilder<XMLConfiguration>(XMLConfiguration.class)
.configure(params.xml()
.setFileName("myconfig.xml")
.setValidating(true));
// This will throw a ConfigurationException if the XML document does not
// conform to its DTD.
XMLConfiguration config = builder.getConfiguration();
Setting the validating
flag to true will cause
XMLConfiguration
to use a validating XML parser. At this parser
a custom ErrorHandler
will be registered, which throws
exceptions on simple and fatal parsing errors.
Validation using a Schema
XML Parsers also provide support for validating XML documents using an
XML Schema. XMLConfiguration
provides a simple mechanism for enabling
this by setting the schemaValidation
flag to true. This
will also set the validating
flag to true so both do not
need to be set. The XML Parser will then use the schema defined in the
XML document to validate it. Enabling schema validation will also
enable the parser's namespace support.
Parameters params = new Parameters();
FileBasedConfigurationBuilder<XMLConfiguration> builder =
new FileBasedConfigurationBuilder<XMLConfiguration>(XMLConfiguration.class)
.configure(params.xml()
.setFileName("myconfig.xml")
.setSchemaValidation(true));
// This will throw a ConfigurationException if the XML document does not
// conform to its Schema.
XMLConfiguration config = builder.getConfiguration();
Default Entity Resolution
There is also some support for dealing with DTD files. Often the
DTD of an XML document is stored locally so that it can be quickly
accessed. However the DOCTYPE
declaration of the document
points to a location on the web as in the following example:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2.2.dtd">
When working with XML documents directly you would use an
EntityResolver
in such a case. The task of such an
entity resolver is to point the XML parser to the location of the
file referred to by the declaration. So in our example the entity
resolver would load the DTD file from a local cache instead of
retrieving it from the internet.
XMLConfiguration
provides a simple default implementation of
an EntityResolver
in form of the
DefaultEntityResolver
class. This implementation is initialized
by calling the registerEntityId()
method with the
public IDs of the entities to be retrieved and their corresponding
local URLs. Then the instance is passed to the configuration builder's
initialization parameters. As an example, consider that the DTD file for
our example document is stored on the class path. We can register it
at XMLConfiguration
using the following code:
Parameters params = new Parameters();
DefaultEntityResolver resolver = new DefaultEntityResolver();
// load the URL to the DTD file from class path
URL dtdURL = getClass().getResource("web-app_2.2.dtd");
// register it at the resolver
resolver.registerEntityId("-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN",
dtdURL);
FileBasedConfigurationBuilder<XMLConfiguration> builder =
new FileBasedConfigurationBuilder<XMLConfiguration>(XMLConfiguration.class)
.configure(params.xml()
.setFileName("web.xml")
.setEntityResolver(resolver)
.setValidating(true));
XMLConfiguration config = builder.getConfiguration();
This basically tells the XML configuration to use the specified
URL when it encounters the given public ID.
Enhanced Entity Resolution
While the default entity resolver can be used under certain circumstances,
it does not work well when using combined configurations from
multiple sources. Furthermore, in many circumstances the programmatic nature of
registering entities will tie the application tightly to the
XML content. In addition, because it only works with the public id it
cannot support XML documents using an XML Schema.
XML
Entity and URI Resolvers describes using a set of catalog files to
resolve entities. Commons Configuration provides support for
this Catalog Resolver through its own
CatalogResolver
class.
<?xml version="1.0" encoding="ISO-8859-1"?>
<Employees xmlns="https://commons.apache.org/employee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://commons.apache.org/employee https://commons.apache.org/sample.xsd">
<Employee>
<SSN>555121211</SSN>
<Name>John Doe</Name>
<DateOfBirth>1975-05-15</DateOfBirth>
<EmployeeType>Exempt</EmployeeType>
<Salary>100000</Salary>
</Employee>
</Employees>
The XML sample above is an XML document using a default namespace of
https://commons.apache.org/employee. The schemaLocation allows a set
of namespaces and hints to the location of their corresponding
schemas. When processing the document the parser will pass the hint,
in this case https://commons.apache.org/sample.xsd, to the entity resolver
as the system id. More information on using schema locations can be found
at schemaLocation.
The example that follows shows how to use the CatalogResolver
class when
creating an XMLConfiguration
. It should be noted that by using the
setEntityResolver()
method any EntityResolver may be used, not just those
provided by Commons Configuration.
Parameters params = new Parameters();
CatalogResolver resolver = new CatalogResolver();
resolver.setCatalogFiles("local/catalog.xml","http://test.org/catalogs/catalog1.xml");
FileBasedConfigurationBuilder<XMLConfiguration> builder =
new FileBasedConfigurationBuilder<XMLConfiguration>(XMLConfiguration.class)
.configure(params.xml()
.setFileName("config.xml")
.setEntityResolver(resolver)
.setSchemaValidation(true)); // enable schema validation
XMLConfiguration config = builder.getConfiguration();
Extending Validation and Entity Resolution
The mechanisms provided with Commons Configuration will hopefully be
sufficient in most cases; however, there will certainly be circumstances
where they are not. XMLConfiguration
provides two extension mechanisms
that should provide applications with all the flexibility they may
need. The first, registering a custom Entity Resolver has already been
discussed in the preceding section. The second is that XMLConfiguration
provides a generic way of setting up the XML parser to use: A preconfigured
DocumentBuilder
object can be passed to the
initialization parameters of the configuration builder.
So an application can create a DocumentBuilder
object
and initialize it according to its special needs. Then this
object must be passed to the configuration builder when it is initialized. When loading
a configuration file, the passed in DocumentBuilder
will
be used instead of the default one. Note: If a custom
DocumentBuilder
is used, the mechanisms for entity
resolution described in the previous sub sections are disabled. The
following example shows how a custom DocumentBuilder
can be set:
Parameters params = new Parameters();
DocumentBuilder docBuilder = ... // set up a custom document builder
FileBasedConfigurationBuilder<XMLConfiguration> builder =
new FileBasedConfigurationBuilder<XMLConfiguration>(XMLConfiguration.class)
.configure(params.xml()
.setFileName("config.xml")
.setDocumentBuilder(docBuilder);
XMLConfiguration config = builder.getConfiguration();
Builder Configuration Related to XML Configurations
XML configurations are created in the typical way: via configuration
builders. The initialization parameters supported for them include all
the settings available for hierarchical configurations and file-based
configurations. In addition, the
XMLBuilderProperties
interface defines settings specific to
XML configurations. This includes
- a custom
DocumentBuilder
- a custom
EntityResolver
- flags whether the XML document is to be validated and how this
validation is to be performed
- the public and the system ID of the document when it is written
A parameters object for an XML configuration can be obtained using
the xml()
method of a
Parameters
instance. It returns an object implementing the
XMLBuilderParameters
interface which defines set
methods for all the available properties.