应该如何以及使用什么注释来修改POJO以获取所需的XML

时间:2022-11-26 10:43:25

I need to generate and XML like in below code snippet where apart from firstName, middleName and lastName there will be many (around 50) elements for a player. For this XML, I need to have POJOs that will be used to generate XML using JAXB. Since, the player elements not only have values but also having attribute as well and according to my understanding I cannot declare properties inside player classes of primitive types rather each element will be a class.

我需要在下面的代码片段中生成和XML,除了firstName,middleName和lastName之外,还有很多(大约50个)元素用于播放器。对于这个XML,我需要使用POJO来使用JAXB生成XML。因为,玩家元素不仅具有值,而且还具有属性,并且根据我的理解,我不能在原始类型的玩家类中声明属性,而是每个元素都是一个类。

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

But I don't want to create these 50 classes rather I think to have a single class that can be used for these all properties for a player but in that case the generated XML will look like:

但我不想创建这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>

What exactly I want here is that a way to give name to 'Property' tag with the value of 'Name' property that is inside the Property class and instead of having two child element viz. 'Name' and 'Value' only value of 'Value' appear in there. I mean how it this possible to get

我在这里想要的是一种给'Property'标签赋予名称的方法,其中'Name'属性的值在Property类中,而不是有两个子元素viz。 “名称”和“价值”仅显示“价值”的值。我的意思是如何才能获得

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

apart from

除了

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

with having POJO as:

将POJO作为:

  • Players.java

    Players.java

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

    class Players {List player; //和getter setter}

  • Player.java

    Player.java

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

    class Player {List property; //和getter setter}

  • Property.java

    Property.java

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

    class Property {String name;字符串值;字符串ID; }

I haven't used any annotation here because I need to know what to put there to get what I want. :)

我没有在这里使用任何注释,因为我需要知道放在那里得到我想要的东西。 :)

1 个解决方案

#1


0  

By this time you probably already solved this, put is a fun exercise and I had some free time.

到这个时候你可能已经解决了这个问题,put是一个有趣的练习,我有一些空闲时间。

Create a class in the package com.quick named StepByStep, remove all the IDE generated code (empty the file) before you coninue.

在名为StepByStep的com.quick包中创建一个类,在连接之前删除所有IDE生成的代码(清空文件)。

First add the package again

首先再次添加包

package com.quick;

First add the imports

首先添加导入

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;

Now, add some up classes

现在,添加一些类

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

Now, add the XmlAdapter class (PlayerTypeAdapter), this is the most important part, if you already know how @XmlJavaTypeAdapter works and you only want to know how to put arbitrary xml inside an element focus here

现在,添加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;
    }
}

And finally add the StepByStep class with its main method (just to test our code)

最后使用main方法添加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));
    }

}

#1


0  

By this time you probably already solved this, put is a fun exercise and I had some free time.

到这个时候你可能已经解决了这个问题,put是一个有趣的练习,我有一些空闲时间。

Create a class in the package com.quick named StepByStep, remove all the IDE generated code (empty the file) before you coninue.

在名为StepByStep的com.quick包中创建一个类,在连接之前删除所有IDE生成的代码(清空文件)。

First add the package again

首先再次添加包

package com.quick;

First add the imports

首先添加导入

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;

Now, add some up classes

现在,添加一些类

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

Now, add the XmlAdapter class (PlayerTypeAdapter), this is the most important part, if you already know how @XmlJavaTypeAdapter works and you only want to know how to put arbitrary xml inside an element focus here

现在,添加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;
    }
}

And finally add the StepByStep class with its main method (just to test our code)

最后使用main方法添加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));
    }

}