[Simple-support] Flattening a hierarchy
Brought to you by:
niallg
|
From: Owen M. <ow...@bi...> - 2011-06-20 16:45:49
|
Hi there...
I'm trying to parse some XML that is flattened and I want to construct an
object with sub-elements. Here's what I'm talking about. If the XML looks
like this:
<person name="Bob">
<address>
<line1>111 11th Street Unit 1A</line1>
<city>New York</city>
<state>NY</state>
<zip>12345</zip>
</address>
<phone>123 456 7890</phone>
</person>
Then I can use the following classes:
public class PersonInfo {
@Attribute
private String name;
@Element(required=false)
private Address address;
@Element(name="phone")
private String phoneNumber;
//implementation
}
But if the XML looks like this:
<person name="Bob">
<line1>111 11th Street Unit 1A</line1>
<city>New York</city>
<state>NY</state>
<zip>12345</zip>
<phone>123 456 7890</phone>
</person>
Then I would have to create a PersonInfo class with the address fields
(line1, etc.) as siblings of the phone field. For reasons required by my
project, I must be able to parse the above flattened XML but serialize and
deserialize the PersonInfo object as it's coded, with an Address object as a
field.
I've looked into using a Visitor to intercept those fields that should
belong to the Address object, but the parser is complaining. Here's the code
I have so far (these are members of the PersonInfo class; I realize it's an
incomplete implementation; just trying to get it to parse for starters).
public static void readFlat() throws Exception {
Serializer s = new Persister(new VisitorStrategy(newPersonVisitor()));
PersonInfo p = s.read(PersonInfo.class, new StringReader(PERSONFLAT
));
System.out.println(p);
}
private static class PersonVisitor implements Visitor {
private Address address;
public void read(Type type, NodeMap<InputNode> node) {
if (node.getName().equals("line1")) {
address = new Address();
node.put("test", "testvalue");
try {
address.setLine1(node.getNode().getValue());
} catch (Exception e) {
address.setLine1("Unable to set line 1 of address");
}
} else if (node.getName().equals("city")) {
try {
address.setCity(node.getNode().getValue());
} catch (Exception e) {
address.setCity("Unable to set city of address");
}
} else if (node.getName().equals("state")) {
try {
address.setState(node.getNode().getValue());
} catch (Exception e) {
address.setState("Unable to set state of address");
}
} else if (node.getName().equals("zip")) {
try {
address.setZip(node.getNode().getValue());
} catch (Exception e) {
address.setZip("Unable to set zip of address");
}
}
//System.out.println("Hi " + node.getName());
}
public void write(Type type, NodeMap<OutputNode> node) {
}
}
Here's what I get from the console as a result:
Exception in thread "main" org.simpleframework.xml.core.ElementException:
Element 'line1' does not have a match in class PersonInfo at line 1
at org.simpleframework.xml.core.Composite.readElement(Composite.java:580)
at org.simpleframework.xml.core.Composite.readElements(Composite.java:502)
at org.simpleframework.xml.core.Composite.readSection(Composite.java:388)
at org.simpleframework.xml.core.Composite.read(Composite.java:368)
at org.simpleframework.xml.core.Composite.readDefault(Composite.java:262)
at org.simpleframework.xml.core.Composite.read(Composite.java:232)
at org.simpleframework.xml.core.Composite.read(Composite.java:202)
at org.simpleframework.xml.core.Composite.read(Composite.java:150)
at org.simpleframework.xml.core.Traverser.read(Traverser.java:92)
at org.simpleframework.xml.core.Persister.read(Persister.java:632)
at org.simpleframework.xml.core.Persister.read(Persister.java:613)
at org.simpleframework.xml.core.Persister.read(Persister.java:591)
at org.simpleframework.xml.core.Persister.read(Persister.java:569)
at org.simpleframework.xml.core.Persister.read(Persister.java:469)
at PersonInfo.readFlat(PersonInfo.java:70)
at PersonInfo.main(PersonInfo.java:115)
I have a feeling I'm using the wrong strategy; that using a Visitor will not
work for my problem. I understand the message above: it's saying that if a
<line1> element exists in the XML, it has to be declared in the PersonInfo
class. I've only just gotten into SimpleXML and so I'm a little unsure of
how I'm going to get it to work properly.
Do you have an idea of how I can make this work?
|