[英]Deserializing multiple different tags (with the same name) with SimpleFramework
我正在使用用于XML序列化/反序列化的简单框架,尽管第一个很容易,但是后者却有问题。 因此,我从服务器收到XML响应,它看起来像这样:
<?xml version="1.0" ?>
<tables>
<table name="result" a="context" b="name">
<r a="stuff1" b="blahblah" />
</table>
<table name="response" a="error" b="reason">
<r a="0" b="" />
</table>
</tables>
是的,它有2个名称为“表”的元素。 问题在于,第一个“表”元素可能具有3个以上的属性,这意味着,我不能只为“表”标签创建通用实体。 因此,我当前的反序列化实体代码如下所示:
@Root(name = "tables", strict = false)
public class Response {
@Element(name = "table", required = false)
@Path("//table[@name='result']")
Result resultTable;
@Element(name = "table")
@Path("//table[@name='result']")
Response responseTable;
public Result getResultTable() {
return resultTable;
}
public void setResultTable(Result resultTable) {
this.resultTable = resultTable;
}
public Response getResponseTable() {
return responseTable;
}
public void setResponseTable(Response responseTable) {
this.responseTable = responseTable;
}
}
不幸的是,它不起作用:我得到一个例外:
org.simpleframework.xml.core.PathException: Path '//[@name='result']' in field 'resultTable'
com.package.Response.resultTable references document root
我尝试了不同的XPath选项,例如简单的通配节点:
@Path("//*[@name='result']")
@Path("*[@name='result']")
但这也不起作用。 所以,是由于错误的XPath选项或Simple Framework的限制引起的我的错:
使用此类注释时要注意的一件事是,仅支持XPath表达式语法的子集。 例如,元素和属性引用不能从文档的根部获取,仅允许当前上下文中的引用。
然后应该与其他XML反序列化器一起使用吗? 谢谢。
您可以尝试使用inline-list来解决此问题。 另一个-我认为更好的解决方案 :对于“如果名称是将结果反序列化为结果,如果将响应反序列化为响应”部分,请使用Converter
。 这听起来比实际要复杂得多!
由于有两个Response
类-一个用于tables
,一个作为table
,我将后一个命名为ResponseTable
; ResultTable
在您的示例中为Result
。 我想您有一些软件包来防止这种情况。
对于两个表,都使用Content
类对<r ... />
元素进行建模。
@Root
public class ResponseTable // 'Response' in your code
{
@Attribute(name = "name")
private String name;
@Attribute(empty = "a")
private String a;
@Attribute(empty = "b")
private String b;
@Element(name = "r")
private Content r;
// ...
}
@Root
public class ResultTable // 'Result' in your code
{
@Attribute(name = "name")
private String name;
@Attribute(empty = "a")
private String a;
@Attribute(empty = "b")
private String b;
@Element(name = "r")
private Content r;
// ...
}
@Root()
public class Content
{
@Attribute(name = "a")
private String a;
@Attribute(name = "b")
private String b;
// ...
}
接下来是有趣的部分:
@Root(name = "tables", strict = false)
@Convert(Response.ResponseConverter.class)
public class Response
{
@Element(name = "table")
private ResultTable resultTable;
@Element(name = "table2")
private ResponseTable responeTable;
// ...
static class ResponseConverter implements Converter<Response>
{
private final Serializer ser = new Persister();
@Override
public Response read(InputNode node) throws Exception
{
Response resp = new Response();
InputNode n = node.getNext();
while( n != null )
{
switch( n.getAttribute("name").getValue() )
{
case "result":
resp.resultTable = ser.read(ResultTable.class, n);
break;
case "response":
resp.responeTable = ser.read(ResponseTable.class, n);
break;
default:
throw new RuntimeException("Unsupported table: "
+ n.getAttribute("name").getValue());
}
n = node.getNext();
}
return resp;
}
@Override
public void write(OutputNode node, Response value) throws Exception
{
// Implement as needed (hint: again use Serializer here)
throw new UnsupportedOperationException("Not supported yet.");
}
}
}
这里会发生什么:
@Convert
用于指定一个Converter
实现,该实现实现Response
类的(反)序列化 ResponseConverter
仅用于确定 <table …>…</table>
元素的类型 (= Response或Result表) Serializer
,使用常规的Serializer
器 -无需手动完成整个工作! 我尚未实现write()
部分,但是如您所见,它并不那么困难; 您可以再次使用Serializer
来完成主要工作。
Converter
: Response
Result
这样就可以拥有多个序列化为xml的类,即使它们共享相同的元素名称。
只需注意一件事:对于@Convert
,必须设置AnnotationStrategy
:
Serializer ser = new Persister(new AnnotationStrategy());
// ^^^^^^^^^^^^^^^^^^^^
final String xml = …
Response response = ser.read(Response.class, xml);
System.out.println(response)
注: 没有必要使用一个AnnotationStrategy
你内的战略Converter
-只要你不依赖于其他Converter
存在。
输出量
(生成的toString()
方法)
Response{resultTable=ResultTable{name=result, a=context, b=name, r=Content{a=stuff1, b=blahblah}}, responeTable=ResponseTable{name=response, a=error, b=reason, r=Content{a=0, b=}}}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.