views:

188

answers:

4

I call an XML document three-layered if its structure is laid out as following: the root element contains some container elements (I'll call them entities), each of them has some simpleType elements inside (I'll call them properties). Something like that:

<data>
 <spaceship>
    <number>1024</number>
    <name>KTHX</name>
 </spaceship>
 <spaceship>
    <number>1624</number>
    <name>LEXX</name>
 </spaceship>
 <knife>
    <length>10</length>
 </knife>
</data>

where spaceship is an entity, and number is a property.

My problem is stated below:

Given

schema: an arbitrary xsd file describing a three-layered document, loaded at runtime. xmlDocument: an xml document conforming to the schema.

Create

A Map<String, Map <String, Object>> containing data from the xmlDocument, where first key corresponds to entity, second key correponds to this entity's property, and the value corresponds to this property's value, after casting it to a proper java type (for example, if the schema sets the property value to be xs:int, then it should be cast to Integer).

What is the easiest way to achieve this result with existing libraries?

P. S. JAXB is not really an option here. The schema might be arbitrary and unknown at compile-time. Also I wish to avoid an excessive use of reflection (associated with converting the beans to maps). I'm looking for something that would allow me to make the typecasts while xml is being parsed.

+2  A: 

I think XMLBeans is worth a shot; saved the day more than once...

Basically you run an ant script to generate the beans handling the schema, then you iterate over the nodes to build your map.

Manrico Corazzi
Well, I have considered static binding and using reflection to create a map from generated beans (akin to commons-beanutils `BeanMap`). However, it seems a bit too unwieldy for me.Maybe there exists a more lightweight approach? I think it should be possible to do the typecasts while parsing the xml, using DOM's `SchemaTypeInfo`, for example.However, I didn't manage to find any ready solution that does it.
kohomologie
+1  A: 

I think JAXB (tutorial here) is the easiest way to do this.

Create your XML structure like:

@XmlRootElement
class data {
 public List<SpaceShipType> spaceship;
 public KnifeType knife;
}

class SpaceShipType {
 public int number;
 public String name;
}

class KnifeType {
 public int length;
}

Then create the object tree, and use JAXB.marshall() to write the XML. If you have an existing XSD, use the xjc tool to create the classes for you.

Tim Jansen
I think that I was a bit unclear while stating my question. The schema is unknown at compile time, everything we know about it is that it describes a three-layered structure.
kohomologie
+1  A: 

You will need reflections if the schema is unknown at compile time.

I suggest to take a look at some other tools like xstream.

I could recommend the simple framework or you could do parsing/wrinting xml with pure dom4j as I did in the timefinder project. I used the 'pure' approach because I had cycles in my object graph, but I wanted that the xml could be validated with an xml schema (and I did not want to use JAXB)

Karussell
A: 

I have finally went with using Castor library for parsing the schema and assigning data types manually.

kohomologie