Apache Commons logo Commons Configuration

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.