Маршалинг и Анмаршалинг или как работать с XML файлами

В данной статье я бы хотел вам продемонстрировать как можно средствами Java сохранять объект в файл xml.

 

Маршалинг  — процесс преобразования представления объекта в памяти в формат данных, пригодный для хранения или передачи. Обычно применяется, когда данные необходимо передавать между различными частями одной программы или от одной программы к другой.

Анмаршалинг — обратный процесс маршалинга.

Процесс маршалинга часто еще называют консервацией, так как этот процесс похож на сериализацию.

Шаг 1.

Для осуществления маршалинга/анмаршалинга нам потребуется библиотека XStream. Скачаейте её с сайта или же подключите dependency в случае, если вы используете maven:

<dependency>
	<groupId>com.thoughtworks.xstream</groupId>
	<artifactId>xstream</artifactId>
	<version>1.4.3</version>
</dependency>

Шаг 2.

Создаем сущность, которую будем сохранять в *.xml.

@XStreamAlias("Person")
public class Person {

    @XStreamAlias("Name")
    private String firstName;

    @XStreamAlias("LastName")
    private String lastName;

    @XStreamAlias("Age")
    @XStreamAsAttribute
    private int age;

    @XStreamAlias("Children")
    private List<Person> children = new ArrayList<Person>();

    public Person() {
    }

    public Person(String firstName, String lastName, int age, List<Person> children){
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
        this.children = children;
    }

    public Person(String firstName, String lastName, int age){
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    public void setChildren(Person children) {
        this.children.add(children);
    }

    public List<Person> getChildren() {
        return children;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return "Person{" +
                    "firstName: " + firstName + ", " +
                    "lastName: " + firstName + ", " +
                    "age: " + age + ", " +
                    (children.size() > 0 ? "Children{ " + children + " } " : "") +
               "}";
    }

}

Описание аннотаций:

@XStreamAlias(<name>) — аннотирует классы, переменные и указывает будущее имя тега для xml файла.

Пример:

@XStreamAlias("Person")
public class Person {
}

Тогда в xml получится следующее:

<Person />

@XStreamAsAttribute — аннотирует только переменные класса, назначая их атрибутом.

Пример:

@XStreamAlias("Person")
public class Person {

    @XStreamAlias("Age")
    @XStreamAsAttribute
    private int age;

}

Тогда в xml получится следующее:

<Person Age="0" />

Обратите внимание на то, что и переменная age аннотируется как @XStreamAlise(«Age»), так мы указываем на то, что данный атрибут будет именоваться в xml файле как Age.

Пример вложенности:

Ниже продемонстрирован пример вложенного тега xml.

@XStreamAlias("Person")
public class Person {

    @XStreamAlias("Name")
    private String firstName;

    @XStreamAlias("Age")
    @XStreamAsAttribute
    private int age;

}

В результате маршалинга данный пример будет выглядеть так:

<Person Age="0">
    <Name>You Name</Name>
</Person>

Шаг 3 — Маршалинг.

Теперь для сущности Person создадим метод, который будет выполнять маршалинг.

public static void marshaller(List<Person> object, String nameXmlFile) throws IOException {
    XStream xStream = new XStream(new DomDriver());
    xStream.alias(nameXmlFile, List.class);
    xStream.processAnnotations(Person.class);

    String xml = xStream.toXML(object);
    saveToFile(xml, nameXmlFile);
}

private static void saveToFile(String xml, String nameFile) throws IOException {
    BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(new File(nameFile+".xml")));
    bufferedWriter.write(xml);
    bufferedWriter.close();
}

Метод marshaller() выполняет маршалинг объекта Person.

Тут мы указываем на то, что корневым объектом маршалинга будет List:

xStream.alias(nameXmlFile, List.class);

Дальше указываем, что List хранит аннотированный объект:

xStream.processAnnotations(Person.class);

После чего можно выполнять маршалинг вызвав метод toXML():

String xml = xStream.toXML(object);

После того как мы выполнили маршалинг, можно сохранять содержимое переменной xml в файл, для этого используется метод saveToFile(String xml, String nameFile).

Шаг 4 — Анмаршалинг

public static List<Person> unmarshalling(File file) throws IOException, ClassNotFoundException {
    XStream xStream = new XStream(new DomDriver());
    xStream.alias("persons", List.class);
    xStream.alias("Person", Person.class);
    xStream.aliasField("Name", Person.class, "firstName");
    xStream.aliasField("LastName", Person.class, "lastName");
    xStream.aliasField("Children", Person.class, "children");
    xStream.aliasAttribute(Person.class, "age", "Age");
    xStream.registerConverter((Converter) new EncodedByteArrayConverter());

    return (ArrayList<Person>) xStream.fromXML(file);
}

В данном методе мы выполняем анмаршалинг — обратный процесс, а точней вытягиваем данные из xml файла в объект.

Тут мы с помощью методов alias(<xmlTagName>, <Object>), aliasField(<classAttribute>, <Object>, <xmlTagName>), aliasAttribute(<Object>, <classAttribute>, <xmlTagName>) говорим XStrem-у как нужно парсить файл и в какие поля класса какие значения проставлять.

Шаг 5.

Запускаем.

public static void main(String[] args) throws IOException, ClassNotFoundException {
    List<Person> myPerson = new ArrayList<Person>();
    List<Person> children = new ArrayList<Person>();
    children.add(new Person("Bob", "Jeckson", 2));
    myPerson.add(new Person("Adam", "Jeckson", 19, children));
    myPerson.add(new Person("Ketty", "Pretorius", 19));

    String nameXmlFile = "persons";
    marshaller(myPerson, nameXmlFile);
    List<Person> persons = unmarshalling(new File(nameXmlFile.concat(".xml")));

    for(Person p : persons){
        System.out.println(p);
    }
}

 Смотрим результат в консоли:

Person{firstName: Adam, lastName: Adam, age: 19, Children{ [Person{firstName: Bob, lastName: Bob, age: 2, }] } }
Person{firstName: Ketty, lastName: Ketty, age: 19, }
Урок создан: 13 февраля 2013 | Просмотров: 10975 | Автор: Александр Барчук | Правила перепечатки


Добавить комментарий

Добавить комментарий

Ваш e-mail не будет опубликован.

Комментарии:

  • 30 октября 2013 в 08:35

    Аноним

    Спасибо за статью, очень познавательно, пишите еще !

    P.S. у вас в aliasField(, , ) перепутаны 1ый и 3й параметры

    • 30 октября 2013 в 09:58

      Александр Барчук

      Та не вроде правильно.

    • 10 января 2015 в 22:58

      Дефлоратор

      Не, всё правильно.
      У меня тоже сгенерированный Идеей конструктор их местами поменял почему-то:)

  • 30 октября 2013 в 08:39

    Reader

    Может быть стоит экранировать специальные символы <classAttribute> ? :)

  • 25 июля 2014 в 22:53

    kosmoflyko

    А как экранировать специальные символы?

    Просто есть XML экспорт таблицы из MS Access 2013 и часть полей в ней названы по русски с пробелами.
    Пример:

    19
    17

  • 20 февраля 2016 в 12:23

    Pavel

    firstName: Adam, lastName: Adam
    firstName: Bob, lastName: Bob
    firstName: Ketty, lastName: Ketty
    Это нормально, что имя=фамилия?

    • 13 марта 2016 в 15:05

      Игорь

      Автор ошибся и написал в @Override («lastName: » + firstName + «, » +) вместо («lastName: » + lastName + «, » +)