How to Read XML Files into Java Objects

Design
Update 5/31/05: There's also a
simpler example in this how-to. You'll probably want to look at both
of them.
The tutorial uses a hardcoded list of URLs to represent the camera images.
This is not ideal, to say the least. Here's what I really want:
This design gives us tremendous flexibility and extensibility. More
regions may be added to the application over time simply by adding them to the
Region Master; each Region Description file may be created by someone other than
the app writer (me), which will allow individuals to add support for their area
simply by creating an XML file with the proper contents that follows the XSD
above. I can either host that file here, the author can host it, or both
(the RegionMaster entry for each region allows multiple URLs to be defined).
One last desired feature is to fall back to a local copy of the Region Master
and Region Description files if they can't be properly obtained from the web.
This could be done using a default set of XML files upon installation of the
app, or the app can cache the ones it finds on the web (I haven't decided which
is better yet).
Creating the XML and Schema
Well, as you can see, I've already created the XML Schemas I want. I
did this using XMLSpy 2005 Professional, which is a great app. You can
simply hand-enter some sample data, tell XMLSpy to generate the schema from the
data, and clean it up a little bit.
Reading the XML Using JAXB
Using JAXB to Create Classes
JAXB = "Java Architecture for XML Binding." It's Sun's approach for
turning XML into Java objects and vice versa. There are a dozen or more
ways to do this; this is the one I chose. To install it, you need J2SDK
1.4.2 or higher.
- Install JWSDP 1.5 (Java Web Services Developer Pack) from
http://java.sun.com into
c:\Sun\jwsdp-1.5 .
- Add an environment variable JWSDP_HOME =
c:\Sun\jwsdp-1.5
- My Eclipse workspace is set to ...\My Documents\TiVo Projects.
Create a TrafficCam_RegionMaster directory under there.
- Copy RegionMaster.xsd into it.
- Run the following command line:
%JWSDP_HOME%\jaxb\bin\xjc.bat
-p com.bitrazor.jaxb.regionmaster RegionMaster.xsd
- This will create a bunch of Java files.
What you're left with is a whole bunch of classes, each representing a node
in the XML tree. If your schema changes, you'll have to re-run this, of
course.
Creating a Project for This Mess in Eclipse
Since we created all this stuff in a directory underneath our existing
Eclipse workspace, we can add a project to point to it, and Eclipse will pick up
all the right stuff (well, mostly, anyway).
- In Eclipse, do File - New - Java Project, and choose the ...\My
Documents\TrafficCam_RegionMaster directory.
- Right-click on the Project, do Properties, Java Build Path, Add External
JARs, and add the following JARs:
- This project should now build in Eclipse without errors (there's one
warning I ignore).
Download a copy of the TrafficCam_RegionMaster project
Creating a Test Project to Test it Out
Now we want to try it out. First, let's drop a copy of RegionMaster.xml
onto the web here:
http://bitrazor.com/tc/rm/100.0/RegionMaster.xml
This will likely be the permanent future home of this file, unless I change
my mind, in which case it won't.
Next:
- Create a new project in Eclipse called TrafficCam_RegionMaster_Test1.
- Add a package com.bitrazor.test .
- Add a class Main, and check the 'auto-generate Main' checkbox.
- Add a Project Reference to TrafficCam_RegionMaster.
- Add all the same external JARs as we added above.
Download this copy of
Main.java to
see the contents I filled it in with. See the JAXB tutorial, Chapter 2,
for more details (pretty easy to figure out; all of this stuff with JAXB took me
less than 2 hours to get going from install to up & going).
Run it in Eclipse, and see that the Console window shows the ID and name of
the regions listed. Yay! We're unmarshalling XML. That was
pretty easy.
Follow the work in progress, if you care:
Here's how I anticipate it being used in production:
RegionMaster rm = new RegionMaster(someURL);
ArrayList al = rm.getRegionIdentifiers();
Collections.sort(al, new RegionIdentifierCompareByName());
for (Iterator iter = al.iterator(); iter.hasNext();) {
RegionIdentifier rid = (RegionIdentifier)iter.next();
// Display rid.getName() on the Tivo
}
When the user selects a region name, you can use:
ArrayList selectedRegionURLs = rm.getURLsByID(rid.getId());
This will give us back a list of URLs we can use to grab that region's
description file (the one with the cameras listed).
- Changed RegionMaster.xsd to change ID to string (was int); here's the
new copy of RegionMaster.xsd
(source in same dir)
- Created Tivo Projects\jaxbRegionMaster2; re-ran the xjc.bat on the new
xsd & created a new project out of it
- Changed the test project to point to this new one instead of the old one
Additional Notes
Additional JAXB notes may be found here.
|