当前位置:  开发笔记 > 编程语言 > 正文

使用Retrofit反序列化带有文本和子标签的XML标记

如何解决《使用Retrofit反序列化带有文本和子标签的XML标记》经验,为你挑选了1个好方法。

我正在使用Retrofit和SimpleXML来解析来自某些公共API的XML响应.我一直在很好地处理所有内容,直到我偶然发现包含自由文本和子标记的XML标记 - 如以下示例所示:


   Some free-style text
   Even more text!

为了尝试使用Simple-XML注释进行反序列化,我已经采用了两种方式.请记住,基本上'a'是一个条目标签列表:

首先:

@ElementList(entry = "a", inline = true, required = false) List aList;

'A'定义如下:

public static class A {
    @Text(required = false) protected String a;
}

这很好地读取了自由文本部分,但是任何反序列化'b'标记内容的尝试(例如通过将@Elementw或o @Path注释成员添加到类'A')都失败了.我查看了SimpleXML文档,显然使用时存在以下限制@Text:

管理Text注释使用的规则是每个模式类只能有一个.此外,此注释不能与Element注释一起使用.只有属性注释可以与它一起使用,因为此注释不会在拥有元素中添加任何内容.

第二种方法,更简单:

@ElementList(entry = "a", inline = true, required = false) List aList;

再一次,"a"标签的内容得到了正确的反序列化,但是没有办法找到"b"子标签的内容.

如何使用与JAVA对象相关的纯Simple-XML注释,使用关联的'b'子标签对'a'标签的内容进行反序列化?



1> d4vidi..:

虽然这个问题似乎没有引起太多关注,但我仍然在分享我为这个问题找到的解决方案 - 也许其他人可能会受益.

显然,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 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 {

    @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
    }
}

CustomConverter直属的"a"和下"B"的文本到A的在本质上串接的文本的内容content数据成员.

向前迈出了一步

为了充分披露,我还想分享我最终要解决的真正解决方案,这是为了概括我在本文中提到的问题.

我必须反序列化的匿名"a"标记下的内容实际上是HTML标记的文本.例如:


If you can't explain it 
simply
, you don't 

   understand it 
   well enough.

 -- Albert Einstein

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("");
    }
}

注意:在此解决方案中,'a'标记也将被解析为最终字符串.为避免这样做,可以为根节点发出特殊情况concatNodesTree()方法.

推荐阅读
可爱的天使keven_464
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有