d4v*_*idi 3 java xml android simple-framework retrofit
我正在使用Retrofit和SimpleXML来解析来自某些公共API的XML响应.我一直在很好地处理所有内容,直到我偶然发现包含自由文本和子标记的XML标记 - 如以下示例所示:
<a>
Some free-style text
<b>Even more text!</b>
</a>
Run Code Online (Sandbox Code Playgroud)
为了尝试使用Simple-XML注释进行反序列化,我已经采用了两种方式.请记住,基本上'a'是一个条目标签列表:
@ElementList(entry = "a", inline = true, required = false) List<A> aList;
Run Code Online (Sandbox Code Playgroud)
'A'定义如下:
public static class A {
@Text(required = false) protected String a;
}
Run Code Online (Sandbox Code Playgroud)
这很好地读取了自由文本部分,但是任何反序列化'b'标记内容的尝试(例如通过将@Elementw或o @Path注释成员添加到类'A')都失败了.我查看了SimpleXML文档,显然使用时存在以下限制@Text:
管理Text注释使用的规则是每个模式类只能有一个.此外,此注释不能与Element注释一起使用.只有属性注释可以与它一起使用,因为此注释不会在拥有元素中添加任何内容.
@ElementList(entry = "a", inline = true, required = false) List<String> aList;
Run Code Online (Sandbox Code Playgroud)
再一次,"a"标签的内容得到了正确的反序列化,但是没有办法找到"b"子标签的内容.
如何使用与JAVA对象相关的纯Simple-XML注释,使用关联的'b'子标签对'a'标签的内容进行反序列化?
虽然这个问题似乎没有引起太多关注,但我仍然在分享我为这个问题找到的解决方案 - 也许其他人可能会受益.
显然,Simple XML框架的制造者意识到某些XML不符合他们预定义的标准情况(就像我的情况一样).因此,他们在序列化/反序列化覆盖中增加了支持.可以创建自定义转换器类并使用@Convert注释将其应用于特定的XML构造.在自定义转换器中,XML反序列化被"缩减"为非常类似于标准Java org.w3c.dom框架的API .
为了解决我的问题中引入的问题,可以使用以下代码:
// 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)
public class A {
String content = "";
public String getContent() {
return content;
}
}
public class CustomConverter implements Converter<A> {
@Override
public A read(InputNode node) throws Exception {
A a = new A();
String value = node.getValue();
if (value != null) {
a.content = value;
}
InputNode nodeB = node.getNext();
if (nodeB != null) {
value = nodeB.getValue();
if (value != null) {
a.content += value;
}
}
return a;
}
@Override
public void write(OutputNode node, A value) throws Exception {
// N/A
}
}
Run Code Online (Sandbox Code Playgroud)
的CustomConverter直属的"a"和下"B"的文本到A的在本质上串接的文本的内容content数据成员.
为了充分披露,我还想分享我最终要解决的真正解决方案,这是为了概括我在本文中提到的问题.
我必须反序列化的匿名"a"标记下的内容实际上是HTML标记的文本.例如:
<a>
If you can't explain it
<i>simply</i>
, you don't
<i>
understand it
<b>well enough.</b>
</i>
-- Albert Einstein
</a>
Run Code Online (Sandbox Code Playgroud)
HTML标签与整体解析XML无关:我真正需要的是将'a'下的内容反序列化为名为'A'的类下的纯文本.所以这是我的(递归)转换器:
@Override
public A read(InputNode node) throws Exception {
final StringBuilder sb = new StringBuilder(1024);
concatNodesTree(sb, node);
A a = new A();
a.content = sb.toString();
return a;
}
private void concatNodesTree(StringBuilder sb, InputNode root) throws Exception {
if (root.isElement()) {
sb.append("<").append(root.getName()).append(">");
}
String value = root.getValue();
if (value != null) {
sb.append(value);
}
InputNode node = 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(">");
}
}
Run Code Online (Sandbox Code Playgroud)
注意:在此解决方案中,'a'标记也将被解析为最终字符串.为避免这样做,可以为根节点发出特殊情况concatNodesTree()方法.
| 归档时间: |
|
| 查看次数: |
1215 次 |
| 最近记录: |