Deserializing An Xml Tag With Text And Subtags Using Retrofit
Solution 1:
Though this question doesn't seem to have attract much attention, I'm sharing a solution that I've found for this problem anyways - perhaps others could benefit.
Apparently the makers of the Simple XML framework were aware of the fact that some XML's don't fit into their predefined, standard cases (much like in my case). Therefore, they've added support in serialization/deserialization overriding. One can create a custom converter class and use the @Convert
annotation to apply it over specific XML constructs. Within the custom converter, the XML deserialization is 'reduced' to an API very similar to the standard Java org.w3c.dom
framework.
In order to solve the problem introduced in my question, the following code can be used:
// First, declare the 'a' tags in the root class hosting them (this is pretty standard):@ElementList(entry = "a", inline = true) List<A> aList;
// Second, create and apply a custom converter as described:@Root@Convert(CustomConverter.class)publicclassA {
Stringcontent="";
public String getContent() {
return content;
}
}
publicclassCustomConverterimplementsConverter<A> {
@Overridepublic A read(InputNode node)throws Exception {
Aa=newA();
Stringvalue= node.getValue();
if (value != null) {
a.content = value;
}
InputNodenodeB= node.getNext();
if (nodeB != null) {
value = nodeB.getValue();
if (value != null) {
a.content += value;
}
}
return a;
}
@Overridepublicvoidwrite(OutputNode node, A value)throws Exception {
// N/A
}
}
The CustomConverter
in essence concatenates the content of the text directly under the 'a' and the text under 'b' onto A's content
data member.
Taking another step forward
In the interest of full disclosure, I'd also like to share the real solution I ended up going for, which was for a generalization of the problem I asked about in this post.
The content under the anonymous 'a' tag that I had to deserialize was in fact HTML-tagged text. For example:
<a>
If you can't explain it
<i>simply</i>
, you don't
<i>
understand it
<b>well enough.</b></i>
-- Albert Einstein
</a>
HTML tags are irrelevant for the parsing of the XML as a whole: All I really needed was for the content under 'a' to be deserialized as plain-text under a class named 'A'. So here's my (recursive) converter:
@Overridepublic A read(InputNode node)throws Exception {
finalStringBuildersb=newStringBuilder(1024);
concatNodesTree(sb, node);
Aa=newA();
a.content = sb.toString();
return a;
}
privatevoidconcatNodesTree(StringBuilder sb, InputNode root)throws Exception {
if (root.isElement()) {
sb.append("<").append(root.getName()).append(">");
}
Stringvalue= root.getValue();
if (value != null) {
sb.append(value);
}
InputNodenode= root.getNext();
while (node != null) {
concatNodesTree(sb, node);
// Each time a sub-tree is 'over', getValue() will deserialize the potentially upcoming free-text
value = root.getValue();
if (value != null) {
sb.append(value);
}
node = root.getNext();
}
if (root.isElement()) {
sb.append("</").append(root.getName()).append(">");
}
}
Note: In this solution, the 'a' tag would also be parsed into the final string. To avoid doing that, one can issue a special case concatNodesTree() method for the root node.
Post a Comment for "Deserializing An Xml Tag With Text And Subtags Using Retrofit"