Как и какую аннотацию следует использовать для изменения POJO для получения необходимого XML

Мне нужно сгенерировать и XML, как в следующем фрагменте кода, где кроме firstName, middleName и lastName будет много (около 50) элементов для игрока. Для этого XML мне нужно иметь POJO, которые будут использоваться для генерации XML с использованием JAXB. Поскольку элементы player не только имеют значения, но и имеют атрибуты, и, согласно моему пониманию, я не могу объявить свойства внутри классов проигрывателей примитивных типов, а каждый элемент будет классом.

<Players>
    <Player>
        <FirstName id="001">Mahendra</FirstName>
        <MiddleName id="002">Singh</MiddleName>
        <LastName id="003">Dhoni</LastName>
    </Player>
</Player>

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

<Players>
    <Player>
        <Property id="001">
            <Name>FirstName</Name>
            <Value>Mahendra</Value>
        </Property>
        <Property id="002">
            <Name>MiddleName</Name>
            <Value>Sing</Value>
        </Property>
        <Property id="003">
            <Name>LastName</Name>
            <Value>Dhoni</Value>
        </Property>
    </Player>
</Player>

Что именно я хочу здесь, так это способ присвоить имя тегу "Свойство" со значением свойства "Имя", которое находится внутри класса "Свойство", а не иметь два дочерних элемента, а именно. В поле "Имя" и "Значение" отображается только значение "Значение". Я имею в виду, как это можно получить

<FirstName id="001">Mahendra</FirstName>

Помимо

<Property id="001">
    <Name>FirstName</Name>
    <Value>Mahendra</Value>
</Property>

с наличием POJO как:

  • Players.java

    class Players { List<Player> player; //and getter setter }

  • Player.java

    class Player { List<Property> property; // and getter setter }

  • Property.java

    class Property { String name; String value; String id; }

Я не использовал здесь никаких аннотаций, потому что мне нужно знать, что поместить туда, чтобы получить то, что я хочу.:)

1 ответ

К этому времени вы, наверное, уже решили это, но занятие было забавным, и у меня было немного свободного времени.

Создайте класс в пакете com.quick с именем StepByStep, удалите весь сгенерированный код IDE (очистите файл) перед продолжением.

Сначала добавьте пакет снова

package com.quick;

Сначала добавьте импорт

import java.io.*;
import java.util.*;

import javax.xml.bind.*;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.*;
import javax.xml.parsers.*;

import org.w3c.dom.*;
import org.w3c.dom.Element;

Теперь добавьте несколько классов

class Player {List<Property> property = new ArrayList<>();}

class Property {
    String id, name, value;
    public Property(String id, String name, String value) {
        this.id = id;
        this.name = name;
        this.value = value;
    }
}

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD) // or write the get and set methods
class Players {
    @XmlJavaTypeAdapter(PlayerTypeAdapter.class) // dont worry about this line
    List<Player> player;
}

Теперь добавьте класс XmlAdapter (PlayerTypeAdapter), это самая важная часть, если вы уже знаете, как работает @XmlJavaTypeAdapter, и вам нужно только знать, как поместить произвольный xml в фокус элемента здесь

class PlayerTypeAdapter extends XmlAdapter<Object, Player> {

    private DocumentBuilder documentBuilder;

    public PlayerTypeAdapter() {
        try {
            documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        } catch (Exception e) {
        }
    }

    @Override
    public Player unmarshal(Object v) throws Exception {
        Player p = new Player();
        NodeList c = ((Element) v).getChildNodes();
        for (int i = 0; i < c.getLength(); i++) {
            Node n = c.item(i);
            if (!(n instanceof Element)) continue;
            Element e = (Element) n;
            p.property.add(new Property(e.getAttribute("id"), 
                e.getTagName(), e.getTextContent()));
        }
        return p;
    }

    @Override
    public Object marshal(Player v) throws Exception {
        Document document = documentBuilder.newDocument();
        Element root = document.createElement("dummy");
        if (v.property != null) for (Property p : v.property) {
            Element propertyNode = document.createElement(p.name);
            propertyNode.setAttribute("id", p.id);
            propertyNode.setTextContent(p.value);
            root.appendChild(propertyNode);
        }
        return root;
    }
}

И, наконец, добавьте класс StepByStep с его основным методом (просто для проверки нашего кода)

public class StepByStep {

    public static void main(String[] args) throws JAXBException {

        // context, marshaller and unmarshaller
        JAXBContext context = JAXBContext.newInstance(Players.class, Player.class, Property.class);
        Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        Unmarshaller unmarshaller = context.createUnmarshaller();

        // lets fill dummy players
        Players p = new Players();
        p.player = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            Player e = new Player();
            e.property.add(new Property("001", "FirstName", "Mahendra"));
            e.property.add(new Property("002", "MiddleName", "Sing"));
            e.property.add(new Property("003", "LastName", "Dhoni"));
            p.player.add(e);
        }

        // marshal p (original)
        ByteArrayOutputStream os1 = new ByteArrayOutputStream();
        marshaller.marshal(p, os1);
        byte[] ba1 = os1.toByteArray();

        Players q = (Players) unmarshaller.unmarshal(new ByteArrayInputStream(ba1));

        // marshal q (copy)
        ByteArrayOutputStream os2 = new ByteArrayOutputStream();
        marshaller.marshal(q, os2);
        byte[] ba2 = os2.toByteArray();

        // both q and p should be the same
        System.out.println(new String(ba1));
        System.out.println(new String(ba2));
    }

}
Другие вопросы по тегам