Десериализация повторяющихся элементов XML в Simple 2.5.3 (Java)

Допустим, дан следующий XML:

<?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>

Как видите, элемент <Err> может появляться на каждом уровне XML.

Используя Simple, я хотел бы десериализовать этот XML. Итак, я создал следующий класс:

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

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

    public String getText() { return text; }
}

Однако как мне аннотировать классы для <ResC>, <ConRes>, <ConList> и <Con>? Мне действительно нужно объявлять атрибут типа <Err> в каждом отдельном классе, в котором он может появиться? Это похоже на большие накладные расходы. Если это так, то мне пришлось бы проверять каждый объект, если он содержит ошибку.

Есть ли способ лучше и проще? :-)

Спасибо,
Роберт


person Robert Strauch    schedule 01.06.2011    source источник


Ответы (1)


Важно помнить, что Simple XML должен иметь возможность следовать любой структуре, которую вы можете логически сгенерировать, используя классы. Таким образом, вы можете просто создать базовый класс, который использует интерфейс ошибок и применяет шаблон декоратора, чтобы передать все это конкретному классу ошибок, при этом ни один из реализующих объектов не должен знать, что им было дано.

Наверное, это не имело смысла. Как насчет того, что я просто покажу вам... ладно... Я просто пошел и реализовал именно то, о чем думал, и вот результаты (ссылка на полный код):

Основной файл:

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

Он просто работает и отображает результаты.

Класс BaseObject.java:

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

Это класс, который все должно расширять, если оно хочет «Err».

Интерфейс ошибок:

package com.massaiolir.simple.iface;

public interface Error {
    void setErrorText(String errorText);

    String getErrorText();
}

Класс ConcreteError:

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

}

Фактические классы реализации находятся после этой точки. Вы увидите, что они довольно тривиальны, потому что настоящая работа выполняется в классах выше.

Класс Con:

package com.massaiolir.simple.iface;

public class Con extends BaseObject {

}

Класс ConList:

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

Класс ConRes:

package com.massaiolir.simple.iface;

import org.simpleframework.xml.Element;

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

Класс ResC:

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

И это все, что нужно сделать. Довольно просто. Я смог все это выложить за десять минут. На самом деле мне потребовалось больше времени, чтобы написать этот ответ, чем код, который я вам даю. Если вы ничего не понимаете в коде, который я только что написал, дайте мне знать. Я надеюсь, что это поможет вам понять, как вы могли бы сделать что-то подобное.

person Robert Massaioli    schedule 12.06.2011
comment
Большое спасибо за этот пример кода. Это именно то, что я искал :-) - person Robert Strauch; 15.06.2011
comment
@Robert Strauch: Нет проблем, надеюсь, это поможет и другим людям. - person Robert Massaioli; 15.06.2011