The utils/xml package contains code which implements serialization of objects
into XML streams.
This package is built upon the Java ObjectInputStream/ObjectOutputStream.
There are two main classes that read XML streams (files) and one,
XMLOutputStream,
that writes out XML data to streams.
The package tries to
be consistent with the general use of the Java classes. However, XML is quite
a bit different.
The biggest single difference is that XML tags are not intrinsically connected
to classes. Therefore on output, objects are assigned tags. If a tag is not
explicitly assigned to an output object, then
a process is used to come up with a default tag. This process is:
- Use the explicit tag (if present)
- If the object is of type
XMLSerializableForOutput then call the getTag() method
and use the response as the tag.
- For other objects, use a default tag.
On input, there are two parallel classes:
- the XMLInputStream must be told of the mapping
from tags to classes
so that it knows which class to elaborate for a tag.
This class will fully populate the objects with the data, making
all needed connections. Of course, it has to know what
data will be in the stream.
- The XMLTreeBuildingReader
can read streams with no setup, but
the result is a TextTree,
rather than complete Java objects.
IO overview
The key concept is that the XML classes create all the objects dynamically
as they are being read.
All classes used with the XMLInputStream and
XMLOutputStream
must implement writeXMLObject and readXMLObject
but these functions are not called explicitly. Rather, they are called implicitly by the
readObjectWithTag() function.
Interfaces
There are two interface classes that are the glue for making the
XML bind to Java objects.
- XMLSerializableForOutput defines
an interface that allows the XMLOutputStream
to write the Java objects to an XML stream.
- XMLSerializable defines
an interface that extends XMLSerializableForOutput
capabilities, it also allows the XMLInputStream
to read the Java objects from an XML stream.
Reading in from a file stream using XMLInputStream
The following code fragement opens a file, and creates on instance of the "inObject"
from data within the file.
FileInputStream fis = new FileInputStream("trivial.xml");
XMLInputStream xis = new XMLInputStream(new BufferedInputStream(fis));
xis.associateTagToClass(TrivialObjectTag, new XMLTrivialTestObject());
XMLElementHolder xh = xis.readObjectWithTag();
XMLTrivialTestObject inObject = (XMLTrivialTestObject)xh.getValue();
The following code fragement opens a file, and creates
a populated TextTree
from data within the file.
FileInputStream fis = new FileInputStream("trivial.xml");
XMLTreeBuildingReader xtb = new XMLTreeBuildingReader(new BufferedInputStream(fis));
TextTree aTree = xtb.buildTree();
Writing out to a file stream using XMLOutputStream
The XMLOutputStream is an ObjectOutputSttream.
Thus you can construct it with any suitable underlying stream.
Once you have the steam, it is easy to write objects to XML.
You simply call the object's function, passing in the
XMLOutputStream
as the only argument.
Within the object's writeXMLObject function, you
simply write out the member objects
For primative
objects, you specify a tag and invoke writeObject(tag, obj)).
For member objects
that are XMLSerializableForOutput.
all you have to do is call writeXMLObject
as the tag is automatically retrieved.
The writeXMLObject is very simple, you simply invoke writeObject(tag, obj)
for each atomic member variable. The following code is the complete writeXMLObject from
the XMLTrivialTestObject class.
public void writeXMLObject(XMLOutputStream os) throws IOException {
os.writeObject(MessageTag, message);
os.writeObject(CounterTag, counter);
}