Перечисление SimpleXML с учетом регистра

Я пытался создать XML с помощью библиотеки simplexml (v2.6.2) http://simple.sourceforge.net/home.php

XML, который я хочу создать, должен содержать значение перечисления, которое должно быть чувствительным к регистру. Ниже приводится POJO:

 package pojos;

public enum MyEnum {

    NEW("new"),
    OLD("old");

     private final String value;

     MyEnum(String v)
     {
         value = v;
     }

     public String value() {
            return value;
        }

        public static MyEnum fromValue(String v) {
            for (MyEnum c: MyEnum.values()) {
                if (c.value.equals(v)) {
                    return c;
                }
            }
            throw new IllegalArgumentException(v);
        }

}

Ниже приведен код сериализатора:

import java.io.File;

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

import pojos.MyEnum;


public class TestEnum {

    /**
     * @param args
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
        // TODO Auto-generated method stub

        Serializer serializer = new Persister();
        MyEnum example = MyEnum.NEW;
        File result = new File("myenum.xml");

        serializer.write(example, result);

    }

}

Результирующий вывод:

<myEnum>NEW</myEnum>

Желаемый результат:

<myEnum>new</myEnum>

Как мне поступить? Я не могу изменить имя переменной в перечислении, так как это ключевое слово «новый»!

Спасибо.


person zombie    schedule 09.04.2012    source источник


Ответы (3)


После некоторого исследования исходного кода я обнаружил, что библиотека использует интерфейс Transform для преобразования значений в строки. Поведение преобразований перечисления по умолчанию определяется классом EnumTransform. Чтобы настроить это, вы можете определить свой собственный класс Transform. Следующая версия реализации Transform будет вызывать toString() вместо name() по умолчанию для объектов перечисления.

class MyEnumTransform implements Transform<Enum> {
    private final Class type;

    public MyEnumTransform(Class type) {
        this.type = type;
    }

    public Enum read(String value) throws Exception {
        for (Object o : type.getEnumConstants()) {
            if (o.toString().equals(value)) {
                return (Enum) o;
            }
        }
        return null;
    }

    public String write(Enum value) throws Exception {
        return value.toString();
    }
}

Объекты Transform возвращаются из метода match объектами интерфейса Matcher. Объектов Matcher может быть несколько. Библиотека пробует их одну за другой, пока не найдет ту, которая возвращает ненулевой объект Transformer. Вы можете определить свой собственный объект Matcher и передать его в качестве аргумента конструктору класса Persister. Этот объект получит наивысший приоритет.

Persister serializer = new Persister(new Matcher() {
    public Transform match(Class type) throws Exception {
        if (type.isEnum()) {
            return new MyEnumTransform(type);
        }
        return null;
    }
 });

Наконец, вы не забудете определить метод toString для ваших классов перечисления. Затем комбинация приведенных выше кодов выполнит работу по кодированию объектов перечисления с использованием их значений toString.

person weidi    schedule 09.04.2012
comment
Пробовал этот код: public String toString() { return this.value.toLowerCase(); } - person zombie; 09.04.2012
comment
Переопределение в соответствии с приведенным выше кодом не работает, оно по-прежнему показывает NEW, а не new - person zombie; 09.04.2012
comment
@zombie, я пересмотрел свой ответ. я думаю, на этот раз это действительно делает то, что вы ожидаете. - person weidi; 09.04.2012
comment
В прошлый раз я не пробовал код - теперь я вижу, что Matcher match() не может возвращать пользовательские объекты Transform :( - person zombie; 03.07.2012
comment
@zombie Я помню, я пробовал код, и он работал отлично. Итак, что вы подразумеваете под cannot return custom Transform objects? Это проблема компиляции или что-то в этом роде? - person weidi; 03.07.2012
comment
Извините, интересно, в чем была проблема. Ошибка исчезла после очистки проекта. Спасибо ! - person zombie; 03.07.2012
comment
Спасибо за это. Я пытался выяснить, как это сделать с помощью преобразователя, но преобразователь никогда не получает доступ к классу, поэтому нет никакого способа получить доступ к классу Enum аннотированного члена при чтении из XML. - person Avi Cherry; 22.03.2016

Вы должны переопределить toString()

@Override 
public String toString() {
       return this.value.toLowerCase();
}

Затем запишите результаты, используя

serializer.write(example.toString(), result);
person Hardik Mishra    schedule 09.04.2012
comment
Попробуйте serializer.write(example.toString(), результат); я обновил ответ - person Hardik Mishra; 09.04.2012
comment
Извините, мне пришлось снова открыть принятый ответ. Только что заметил, что это изменило мои выходные XML-теги: ‹string›new‹/string› Мне нужно, чтобы теги были myEnum. - person zombie; 09.04.2012
comment
О.. Я огляделся. В API сериализация перечислений использует метод final name() перечисления. Таким образом, вы получите объявленное имя только на выходе. - person Hardik Mishra; 09.04.2012

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

person NimChimpsky    schedule 09.04.2012