Load Properties from XML

J2SE versions prior to 1.5 required you to work directly with the XML parser to load a configuration file and store settings. While it was never difficult, and while the parser is a standard part of the platform, the extra work was a bit of an annoyance. The newly updated java.util.Properties class now offers an easier way to load and store settings for a program: the loadFromXML(InputStream is) and storeToXML(OutputStream os, String comment) methods.

Properties basics

If you aren't familiar with the java.util.Properties class, you use it to store a set of key-value pairs in a file, where the key and value are separated by an equal sign, as shown in Listing 1.


Listing 1. Sample set of properties
foo=bar
fu=baz

Had Listing 1 been loaded into a Properties object, you would then find two keys (foo and fu) and two values (bar for foo and baz for fu). The class supports embedding Unicode strings with \u, but the important thing here is that everything is treated as a String.


Listing 2 shows how to load the properties file and list its current set of keys and values. You just pass an InputStream for the file to the load() method, and each key-value pair is added to the Properties instance. You would then use list() to list all the properties or getProperty() to retrieve an individual one.


Listing 2. Loading properties
import java.util.*;
import java.io.*;

public class LoadSample {
public static void main(String args[]) throws Exception {
Properties prop = new Properties();
FileInputStream fis =
new FileInputStream("sample.properties");
prop.load(fis);
prop.list(System.out);
System.out.println("\nThe foo property: " +
prop.getProperty("foo"));
}
}


Running the LoadSample program produces the output in Listing 3. Notice that the output of the list() method does not produce the list of key-value pairs in the same order they were in the input file. The Properties class stores the set of pairs in a hashtable (in fact, it is a Hashtable subclass), so there is no guarantee for order.


Listing 3. Output from LoadSample
-- listing properties --
fu=baz
foo=bar

The foo property: bar






XML property files

None of this should be new to you. This is how the Properties class has always worked. What is new, however, is the option of loading a set of properties from an XML file. The DTD for that is shown in Listing 4.


Listing 4. Properties DTD
<?xml version="1.0" encoding="UTF-8"?>
<!-- DTD for properties -->
<!ELEMENT properties ( comment?, entry* ) >
<!ATTLIST properties version CDATA #FIXED "1.0">
<!ELEMENT comment (#PCDATA) >
<!ELEMENT entry (#PCDATA) >
<!ATTLIST entry key CDATA #REQUIRED>

If you're not into reading XML DTDs, this essentially says that wrapped within an outer tag is a tag, followed by any number of tags. For each tag, there is a key attribute, with the contents of the entry being its value. Listing 5 shows what the XML version of the properties file in Listing 1 would look like.


Listing 5. XML version of the Properties file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Hi</comment>
<entry key="foo">bar</entry>
<entry key="fu">baz</entry>
</properties>

As Listing 6 shows, reading the XML version of the Properties file isn't much different than reading the older style format.


Listing 6. Reading the XML Properties file
import java.util.*;
import java.io.*;

public class LoadSampleXML {
public static void main(String args[]) throws Exception {
Properties prop = new Properties();
FileInputStream fis =
new FileInputStream("sampleprops.xml");
prop.loadFromXML(fis);
prop.list(System.out);
System.out.println("\nThe foo property: " +
prop.getProperty("foo"));
}
}



Saving XML Properties

The other side of the new Properties capabilities is storing properties to an XML-formatted file. While the store() method will still create a file like that shown in Listing 1, you can now use the new storeToXML() method to create the file shown in Listing 5. Just pass in an OutputStream and a String for the comment and you're done. Listing 7 demonstrates the new storeToXML() method.


Listing 7. Storing Properties as an XML file
import java.util.*;
import java.io.*;

public class StoreXML {
public static void main(String args[]) throws Exception {
Properties prop = new Properties();
prop.setProperty("one-two", "buckle my shoe");
prop.setProperty("three-four", "shut the door");
prop.setProperty("five-six", "pick up sticks");
prop.setProperty("seven-eight", "lay them straight");
prop.setProperty("nine-ten", "a big, fat hen");
FileOutputStream fos =
new FileOutputStream("rhyme.xml");
prop.storeToXML(fos, "Rhyme");
fos.close();
}
}

The output produced from running the program in Listing 7 is shown in Listing 8.


Listing 8. Stored XML file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>Rhyme</comment>
<entry key="seven-eight">lay them straight</entry>
<entry key="five-six">pick up sticks</entry>
<entry key="nine-ten">a big, fat hen</entry>
<entry key="three-four">shut the door</entry>
<entry key="one-two">buckle my shoe</entry>
</properties>





Conclusion

The choice of using an XML file or older-style a=b type file is completely up to you. The older style is certainly lighter weight from a memory perspective. However, pervasiveness of XML, one would expect the XML format to be popular, as it is widely used already, just not by means of the Properties object. The choice is completely up to you. Examine the source for the package private XMLUtils class for additional information about the XML parsing used.


0 comments: