简体   繁体   中英

JAXB: Use @XmlIDREF on a Map


I'm trying to marshall some data with JAXB. My problem is the following: I have a class Frame which contains a map of signals.

@XmlRootElement(name = "frame")
@XmlAccessorType(XmlAccessType.FIELD)
public class Frame extends V_Element {


    @XmlElementWrapper(name = "signals")
    private Map<Signal, Double> signals;

}

So far the XML output is:

    <frame id="ee61b926-a1ca-4462-ac58-77d3ac0cbe5e" name="F1">
        <signals>
            <entry>
                <key id="7352beaa-1921-4bfe-b1ce-3d8dabe69e8b" name="Signal1">
                    <properties/>
                    <bitLength>0</bitLength>
                    <frame>3ee61b926-a1ca-4462-ac58-77d3ac0cbe5e</frame>
                </key>
                <value>1.0</value>
            </entry>
        </signals>
    </frame>

But instead i want to have the following schema:

    <frame id="3ee61b926-a1ca-4462-ac58-77d3ac0cbe5e" name="F1">

        <signals>
            <signal pos= "1.0">7352beaa-1921-4bfe-b1ce-3d8dabe69e8b</sgnal>
        </signals>
    </frame>

Under the frame tag i want just to have the signal ID and the pos value as an attribute. The @XmlIDREF annotation doesn't work on a Map.

The relation between Signal and Frame is a many-to-many relationship so a Signal has a different position in different Frames. Any leads ?

In order to get that kind of output your POJOs might look like

@XmlAccessorType(XmlAccessType.FIELD)
public class Signal {

    @XmlAttribute(name = "pos", required=true)
    private Double pos;
    @XmlValue
    private String id;

    public String getId(){
        return id;
    }
    public Double getPos(){
        return pos;
    }
    public void setPos(Double p){
        pos = p;
    }
    public void setId(String id){
        this.id = id;
    }
}


public class SignalWrapper {

    @XmlElement(name="signal", required=true)
    private List<Signal> signalList;

    public List<Signal> getSignalList(){
        if(signalList == null)
            signalList = new ArrayList<>();

        return signalList;
    }
  //no setter for Signal list is necessary

}

@XmlRootElement(name="frame")
@XmlAccessorType(XmlAccessType.FIELD)
public class Frame {

    @XmlAttribute(name="id", required=true)
    private String id;

    @XmlAttribute(name="name", required=true)
    private String name;

    @XmlElement(name="signals", required=true)
    private SignalWrapper sigWrapper;

    public String getId(){
        return id;
    }
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name;
    }
    public void setId(String id){
        this.id = id;
    }

    public SignalWrapper getSigWrapper(){
        return sigWrapper;
    }
    public void setSignalWrapper(SignalWrapper sw){
        sigWrapper = sw;
    }


}

Your test code might look like

final String ENT_XML = "C:\\test\\Signal.xml";

            JAXBContext context = JAXBContext.newInstance(Frame.class);

              Marshaller m =  context.createMarshaller();

              Signal s = new Signal();
              s.setId("7352beaa-1921-4bfe-b1ce-3d8dabe69e8b");
              s.setPos(2.0);

              SignalWrapper sw = new SignalWrapper();

              List<Signal> sl = sw.getSignalList();
              sl.add(s);

              Frame f = new Frame();
              f.setSignalWrapper(sw);
              f.setId("3ee61b926-a1ca-4462-ac58-77d3ac0cbe5e");
              f.setName("F1");

              m.marshal(f, new File(ENT_XML));

I've managed to get the schema that i wanted. I have added a class SignalPos

public class SignalPos {

    @XmlAttribute(name = "id")
    @XmlIDREF
    private Signal signal;
    @XmlAttribute
    private Double pos;

    public SignalPos() {
    }

    public SignalPos(Signal s, double pos) {
        this.signal = s;
        this.pos = pos;
    }

    public Signal getSignal() {
        return signal;
    }

    public Double getPos() {
        return pos;
    }

}

And in the Frame class

public class Frame {
    @XmlElementWrapper(name = "signals")
    @XmlElement(name = "signal")
    private List<SignalPos> signals;

}

The output:

    <signals>
        <signal id="d1c23562-d02c-439a-8e7b-d4222c7750c8" pos="23.0"/>
        <signal id="932d8850-36e3-467b-8a62-1e0ae6bb271a" pos="2.0"/>
        <signal id="2e6a99b2-95f8-4a5f-bf44-1ce948839e9d" pos="1.0"/>
    </signals>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM