If you've ever tried to parse an XML file into a set of Java objects, you'll know that you have to jump through hoops to do so. Creating a "SAXParser"1 is easy enough, but in order to actually do anything with the parsed document, you have to create a so-called XML Handler (a subclass of "DefaultHandler") to help you.

Now the first time you write a parser, this is fine. You define an XML Handler, give it a stack, write a bunch of "if-then-else" statements to handle the various element names etc., and set it off to generate your objects.

The second time, it's a bit easier, since you've done it before. You take your previously-build parser, substitute different element and object names into your if statements, tweak it arbitrarily, and set it going again.

The third time, you start to wonder to yourself: why am I reusing all this code? Surely there are some basic principles that I could follow to write my handler once, and use it multiple times?

This project is an attempt at generalising an XML handler. Let's start with the xml file below:

<?xml version="1.0"?>
<cheese-reviews>
	<reviewer name="Alice">
		<cheese name="Cheddar" pungency="0.5"/>
		<cheese name="Epoisses" pungency="5.0"/>
		<cheese name="Stilton" pungency="9.5"/>
		<cheese name="Brie" pungency="1.0"/>
		<about>When not tasting edible cheeses, Alice likes to listen to 80's pop music and watch Disney movies</about>
	</reviewer>
	<reviewer name="Bob">
		<cheese name="Cheddar" pungency="1.0"/>
		<cheese name="Edam" pungency="0.5"/>
		<cheese name="Gruyere" pungency="3.5"/>
		<about>With over 20 years in the dairy industry, Bob certainly knows his way around a cow!</about>
	</reviewer>
</cheese-reviews>

What actual sequence of Java constructor and method calls does that suggest to you? To me, it suggests:

ArrayList<Reviewer> cheeseReviews = new ArrayList<Reviewer>();
Reviewer alice = new Reviewer();
alice.setName("Alice");

Cheese cheddar = new Cheese();
cheddar.setName("Cheddar");
cheddar.setPungency(0.5);
alice.add(cheddar);

Cheese epoisses = new Cheese();
epoisses.setName("Epoisses");
epoisses.setPungency(5.0);
alice.add(epoisses);

<elided for sanity>

alice.addAbout("When not tasting edible cheeses, Alice likes to listen to 80's pop music and watch Disney movies");
cheeseReviews.add(alice);

Reviewer bob = new Reviewer();
bob.setName("Bob");

<elided for sanity>

cheeseReviews.add(bob);
return cheeseReviews;

And thus, QuickAndDirtyXMLHandler was born. And after implementing Cheese and Reviewer — as simple POJOs (Plain Old Java Objects) — and adding the neccessary methods above, the cheesy xml file above was parsed very nicely indeed.

If you're interested, I'm releasing the code under the LGPL: here's the binary and here's the source (including cheeses).

It's still got plenty that I'm wanting to do with it — for example, so far it only looks for String setters, rather than int, float, etc., which isn't ideal. But it's a good start for now.

[1] I won't cover DOM parsing here, because I'm not very familiar with it.

ext_79424: Line drawing of me, by me (Default)

From: [identity profile] spudtater.livejournal.com


I suppose I'm starting from the assumption that you want these objects to all be created. But if you're using XML as a data base, then yes, I see your point.
.

Profile

spudtater: (Default)
spudtater

Most Popular Tags

Powered by Dreamwidth Studios

Style Credit

Expand Cut Tags

No cut tags