Deserialize repeating XML elements in Simple 2.5.3 (Java)

那年仲夏 提交于 2019-12-04 05:26:52

问题


Let's say the following XML is given:

<?xml version="1.0" encoding="UTF-8"?>
<ResC>
    <Err text="Error text 1"/>
    <ConRes>
        <Err text="Error text 2"/>
        <ConList>
            <Err text="Error text 3"/>
            <Con>
                <Err text="Error text 4"/>
            </Con>
        </ConList>
    </ConRes>
</ResC>

As you can see the <Err> element may appear on every level of the XML.

Using Simple I would like to deserialize this XML. So, I have created the following class:

@Element(required=false)
public class Err {
    @Attribute
    private String text;

    public void setText(String text) { this.text = text; }

    public String getText() { return text; }
}

However, how do I have to annotate the classes for <ResC>, <ConRes>, <ConList> and <Con>? Do I really have to declare an attribute of type <Err> in every single class in which it may appear? This seems like a lot of overhead. If so, then I would have to check every single object if it contains an error.

Is there any better and easier way? :-)

Thanks,
Robert


回答1:


The important thing to remember is that Simple XML should be able to follow any structure that you can logically generate using classes. So you could just create a BaseClass that uses an error interface and applies the Decorator pattern so that it passes all of that through to a concrete error class without any of the implementing objects needing to know what they have been given.

That probably made no sense. How about I just show you...okay...I just went away and implemented exactly what I was thinking and here are the results (full code link):

The Main File:

package com.massaiolir.simple.iface;

import java.io.File;

import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

public class Main {
    public static void main(String[] args) throws Exception {
        Serializer serial = new Persister();
        ResC resc = serial.read(ResC.class, new File("data/testdata.xml"));

        System.out.println(" == Printing out all of the error text. == ");
        System.out.println(resc.getErrorText());
        System.out.println(resc.conRes.getErrorText());
        System.out.println(resc.conRes.conList.getErrorText());
        for (Con con : resc.conRes.conList.cons) {
            System.out.println(con.getErrorText());
        }
        System.out.println(" == Finished printing out all of the error text. == ");
    }
}

It just runs simple and displays the results.

The BaseObject.java class:

package com.massaiolir.simple.iface;

import org.simpleframework.xml.Element;

public class BaseObject implements Error {
    @Element(name = "Err", required = false, type = ConcreteError.class)
    private Error err;

    @Override
    public String getErrorText() {
        return err.getErrorText();
    }

    @Override
    public void setErrorText(String errorText) {
        err.setErrorText(errorText);
    }
}

This is the class that everything should extend if it wants 'Err'.

The Error interface:

package com.massaiolir.simple.iface;

public interface Error {
    void setErrorText(String errorText);

    String getErrorText();
}

The ConcreteError class:

package com.massaiolir.simple.iface;

import org.simpleframework.xml.Attribute;

public class ConcreteError implements Error {
    @Attribute
    private String text;

    @Override
    public String getErrorText() {
        return text;
    }

    @Override
    public void setErrorText(String errorText) {
        this.text = errorText;
    }

}

The actual implementing classes are after this point. You will see that they are rather trivial because the real work is being handled in the classes above.

The Con class:

package com.massaiolir.simple.iface;

public class Con extends BaseObject {

}

The ConList class:

package com.massaiolir.simple.iface;

import java.util.ArrayList;

import org.simpleframework.xml.ElementList;

public class ConList extends BaseObject {
    @ElementList(entry = "Con", inline = true)
    public ArrayList<Con> cons;
}

The ConRes class:

package com.massaiolir.simple.iface;

import org.simpleframework.xml.Element;

public class ConRes extends BaseObject {
    @Element(name = "ConList")
    public ConList conList;
}

The ResC class:

package com.massaiolir.simple.iface;

import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;

@Root
public class ResC extends BaseObject {
    @Element(name = "ConRes")
    public ConRes conRes;
}

And that is all that there is to it. Pretty simple right. I was able to bang that all out in ten minutes. It actually took me longer to write this response than it took me to write the code that I am giving you. If you do not understand anything about the code that I have just written then please let me know. I hope this helps you to understand how you might go about doing something like this.



来源:https://stackoverflow.com/questions/6197196/deserialize-repeating-xml-elements-in-simple-2-5-3-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!