I have the following situtation in deserializing xml using SimpleFramework of specific format that cannot be changed...
<Question ID="Q1">
THIS INNER TEXT IS THE ISSUE
<Criteria Type="Normal" Source="OEM">
<Value Type="0">45.7</Value>
<Value Type="100">42.7</Value>
</Criteria>
<Criteria Type="Impact" Source="OEM">
<Value Type="0">45.7</Value>
<Value Type="100">42.7</Value>
</Criteria>
<!-- CRITERIA CAN HAVE ANY NUMBER -->
</Question>
and here is the class I wrote for Question
@Root (name="Question")
public class Question {
@Attribute (name="ID")
private String id;
@ElementList (inline=true, required=false)
private List<Criteria> criteria;
@Text
private String text;
// And their getter and setters...
}
Now the issue is that, I CANNOT GET INNER TEXT...
Can anybody suggest me the way to do this...???
You can't use @Text
annotation here, this is only possible if you don't have any child.
and it [
@Text
annotation] can not appear with the another XML element annotations, such as theElement
annotation.
Source: @Text
API documentation
However, you can use a Converter
to those text. This is a bit tricky, but here's an example:
Criteria
class:
@Root(name = "Criteria")
public class Criteria
{
@Attribute(name = "Type")
private String type;
@Attribute(name = "Source")
private String source;
@ElementList(name = "Values", inline = true)
private ArrayList<Value> values;
public Criteria(String type, String source)
{
this.type = type;
this.source = source;
this.values = new ArrayList<>();
}
private Criteria() { }
// ...
@Override
public String toString()
{
return "Criteria{" + "type=" + type + ", source=" + source + ", values=" + values + '}';
}
// Inner class for values - you also can use a normal one instead
@Root(name = "Value")
public static class Value
{
@Attribute(name = "Type", required = true)
private int type;
@Text(required = true)
private double value;
public Value(int type, double value)
{
this.type = type;
this.value = value;
}
private Value() { }
}
}
Question
class:
@Root(name = "Question")
@Convert( value = Question.QuestionConvert.class)
public class Question
{
@Attribute(name = "ID", required = true)
private String id;
@Element(name = "text")
private String text;
@ElementList(inline = true)
private ArrayList<Criteria> criteria;
public Question(String id)
{
this.id = id;
this.criteria = new ArrayList<>();
this.text = "This inner text ...";
}
private Question() { }
// ...
@Override
public String toString()
{
return "Question{" + "id=" + id + ", text=" + text + ", criteria=" + criteria + '}';
}
static class QuestionConvert implements Converter<Question>
{
private final Serializer ser = new Persister();
@Override
public Question read(InputNode node) throws Exception
{
Question q = new Question();
q.id = node.getAttribute("ID").getValue();
q.text = node.getValue();
q.criteria = new ArrayList<>();
InputNode criteria = node.getNext("Criteria");
while( criteria != null )
{
q.criteria.add(ser.read(Criteria.class, criteria));
criteria = node.getNext("Criteria");
}
return q;
}
@Override
public void write(OutputNode node, Question value) throws Exception
{
node.setAttribute("ID", value.id);
node.setValue(value.text);
for( Criteria c : value.getCriteria() )
{
ser.write(c, node);
}
}
}
}
Please note all those empty constructors. They are required by simple but you can keep them private. You don't have to implement those inner classes as inner.
The key to the solution is the Converter
which allows you to use text and child-elements together. You can use a Serializer
to write all the Criteria
-childs.
There are some toString()
methods, those are only for testing - you can implement them as you need.
Input XML:
<Question ID="Q1">This inner text ...
<Criteria Type="Normal" Source="OEM">
<Value Type="0">45.7</Value>
<Value Type="100">42.7</Value>
</Criteria>
<Criteria Type="Impact" Source="OEM">
<Value Type="0">45.7</Value>
<Value Type="100">42.7</Value>
</Criteria>
</Question>
Example code:
Serializer ser = new Persister(new AnnotationStrategy()); // Don't miss the AnnotationStrategy!
Question q = ser.read(Question.class, f);
System.out.println(q);
Output:
Question{id=Q1, text=This inner text ...
, criteria=[Criteria{type=Normal, source=OEM, values=[Value{type=0, value=45.7}, Value{type=100, value=42.7}]}, Criteria{type=Impact, source=OEM, values=[Value{type=0, value=45.7}, Value{type=100, value=42.7}]}]}
Not very beautiful, but it's working! :-)
Ps. Since both methods of the Converter are implemented you also can use this code to serialize a Question
object.
来源:https://stackoverflow.com/questions/17462970/simpleframwork-xml-element-with-inner-text-and-child-elements