Using XML based ConfigurationsThis section explains how to use hierarchical and structured XML datasets. Hierarchical properties
Because of its
tree-like nature XML documents can represent data that is
structured in many ways. This section explains how to deal with
such structured documents and demonstrates the enhanced query
facilities supported by the Accessing properties defined in XML documents
We will start with a simple XML document to show some basics
about accessing properties. The following file named
<?xml version="1.0" encoding="ISO-8859-1" ?> <gui-definition> <colors> <background>#808080</background> <text>#000000</text> <header>#008000</header> <link normal="#000080" visited="#800080"/> <default>${colors.header}</default> </colors> <rowsPerPage>15</rowsPerPage> <buttons> <name>OK,Cancel,Help</name> </buttons> <numberFormat pattern="###\,###.##"/> </gui-definition>
(As becomes obvious, this tutorial does not bother with good
design of XML documents, the example file should rather
demonstrate the different ways of accessing properties.)
To access the data stored in this document it must be loaded
by try { XMLConfiguration config = new XMLConfiguration("tables.xml"); // do something with config } catch(ConfigurationException cex) { // something went wrong, e.g. the file was not found } If no exception was thrown, the properties defined in the XML document are now available in the configuration object. The following fragment shows how the properties can be accessed: String backColor = config.getString("colors.background"); String textColor = config.getString("colors.text"); String linkNormal = config.getString("colors.link[@normal]"); String defColor = config.getString("colors.default"); int rowsPerPage = config.getInt("rowsPerPage"); List buttons = config.getList("buttons.name");
This listing demonstrates some important points about constructing
keys for accessing properties load from XML documents and about
features of
In the next section will show how data in a more complex XML document can be processed. Structured XMLConsider the following scenario: An application operates on database tables and wants to load a definition of the database schema from its configuration. A XML document provides this information. It could look as follows: <?xml version="1.0" encoding="ISO-8859-1" ?> <database> <tables> <table tableType="system"> <name>users</name> <fields> <field> <name>uid</name> <type>long</type> </field> <field> <name>uname</name> <type>java.lang.String</type> </field> <field> <name>firstName</name> <type>java.lang.String</type> </field> <field> <name>lastName</name> <type>java.lang.String</type> </field> <field> <name>email</name> <type>java.lang.String</type> </field> </fields> </table> <table tableType="application"> <name>documents</name> <fields> <field> <name>docid</name> <type>long</type> </field> <field> <name>name</name> <type>java.lang.String</type> </field> <field> <name>creationDate</name> <type>java.util.Date</type> </field> <field> <name>authorID</name> <type>long</type> </field> <field> <name>version</name> <type>int</type> </field> </fields> </table> </tables> </database>
This XML is quite self explanatory; there is an arbitrary number
of table elements, each of it has a name and a list of fields.
A field in turn consists of a name and a data type. This
XML document (let's call it When we now want to access some of the properties we face a problem: the syntax for constructing configuration keys we learned so far is not powerful enough to access all of the data stored in the tables document.
Because the document contains a list of tables some properties
are defined more than once. E.g. the configuration key
Multiple definitions of a property do not cause problems and are
supported by all classes of Configuration. If such a property
is queried using Object prop = config.getProperty("tables.table.name"); if(prop instanceof Collection) { System.out.println("Number of tables: " + ((Collection) prop).size()); }
An alternative to this code would be the Accessing structured properties
Okay, we can obtain a list with the name of all defined
tables. In the same way we can retrieve a list with the names
of all table fields: just pass the key
When working with such hierarchical structures the configuration keys
used to query properties can have an extended syntax. All components
of a key can be appended by a numerical value in parentheses that
determines the index of the affected property. So if we have two
We will now provide some configuration keys and show the results
of a
These examples should make the usage of indices quite clear. Because each configuration key can contain an arbitrary number of indices it is possible to navigate through complex structures of XML documents; each XML element can be uniquely identified. Adding new properties
So far we have learned how to use indices to avoid ambiguities when
querying properties. The same problem occurs when adding new
properties to a structured configuration. As an example let's
assume we want to add a new field to the second table. New properties
can be added to a configuration using the // Warning: This might cause trouble! config.addProperty("tables.table.fields.field.name", "size");
would not be sufficient because it does not contain all needed
information. How is such a statement processed by the
The following parts of the key are processed in exactly the same
manner. Under the selected ... <table tableType="application"> <name>documents</name> <fields> <field> <name>docid</name> <type>long</type> </field> <field> <name>name</name> <type>java.lang.String</type> </field> <field> <name>creationDate</name> <type>java.util.Date</type> </field> <field> <name>authorID</name> <type>long</type> </field> <field> <name>version</name> <name>size</name> <== Newly added property <type>int</type> </field> </fields> </table> </tables> </database>
This result is obviously not what was desired, but it demonstrates
how
If we want a different behavior, we must explicitely tell
config.addProperty("tables.table(1).fields.field(-1).name", "size"); config.addProperty("tables.table(1).fields.field.type", "int");
The first line in this fragment specifies that a new branch is
to be created for the // Add a new table element and define the name config.addProperty("tables.table(-1).name", "versions"); // Add a new field to the new table // (an index for the table is not necessary because the latest is used) config.addProperty("tables.table.fields.field(-1).name", "id"); config.addProperty("tables.table.fields.field.type", "int"); // Add another field to the new table config.addProperty("tables.table.fields.field(-1).name", "date"); config.addProperty("tables.table.fields.field.type", "java.sql.Date"); ...
For more information about adding properties to a hierarchical
configuration also have a look at the javadocs for
Escaping dot characters in XML tagsIn XML the dot character used as delimiter by most configuration classes is a legal character that can occur in any tag. So the following XML document is completely valid: <?xml version="1.0" encoding="ISO-8859-1" ?> <configuration> <test.value>42</test.value> <test.complex> <test.sub.element>many dots</test.sub.element> </test.complex> </configuration>
This XML document can be loaded by
Of course, it is the dot character contained in the property
names, which causes this problem. A dot is always interpreted
as a delimiter between elements. So given the property key
int testVal = config.getInt("test..value"); String complex = config.getString("test..complex.test..sub..element"); Note the duplicated dots whereever the dot does not act as delimiter. This way it is possible to access properties containing dots in arbitrary combination. However, as you can see, the escaping can be confusing sometimes. So if you have a choice, you should avoid dots in the tag names of your XML configuration files. Validation of XML configuration files
XML parsers provide support for validation of XML documents to ensure that they
conform to a certain DTD. This feature can be useful for
configuration files, too.
The easiest way to turn on validation is to simply set the
XMLConfiguration config = new XMLConfiguration(); config.setFileName("myconfig.xml"); config.setValidating(true); // This will throw a ConfigurationException if the XML document does not // conform to its DTD. config.load();
Setting the
While using the
So an application can create a |