1

I am trying to implement some code so I can marshall and unmarshall some xml using JAXB.

Basically, I have a xml in the following format:

<root attribute1="blabla" attribute2="blablabla">
    <register type="1" description="blabla">
        <field description = "blabla" type = "blabla">
    </register>
    <register type="2" description="blabla">
        <field description = "blabla" type = "blabla">
    </register>
</root>

I want to create a HashMap if Registers, where its key is the register type and its value is the register itself.

I am not sure how to do it. Is it possible? I have already tried to use Adapters, but it didn't work.

Can anyone help me here?

1 Answers1

1

With an XmlAdapter on a Map (to convert the Map to a domain object with a List of Register objects) you are going to be able to produce/consume XML that looks like the following (Note the addition of the registers element):

<root attribute1="blabla" attribute2="blablabla">
  <registers>
    <register type="1" description="blabla">
        <field description = "blabla" type = "blabla">
    </register>
    <register type="2" description="blabla">
        <field description = "blabla" type = "blabla">
    </register>
  </registers>
</root>

If you use EclipseLink MOXy as your JAXB provider, then you can use our @XmlPath extension to get rid of that extra element.

@XmlJavaTypeAdapter(MapAdapter.class)  // Standard JAXB annotation
@XmlPath(".") // MOXy extension
private Map<String, Register> registers;

UPDATE

Unfortunatelly I can't use MOXy in this project and I can't change the xml. Is there any way of parsing it without the registers tag?

This isn't the prettiest solution, but you could do the following (note: with this solution it is not safe to marshal the same instance of Root concurrently):

import java.util.*;
import javax.xml.bind.annotation.*;

@XmlRootElement
public class Root {

    private Map<String, Register> registers = new HashMap<String, Register>();

    @XmlElement(name="register")
    private Collection<Register> registerCollection;

    @XmlTransient
    public Map<String, Register> getRegisters() {
        return registers;
    }

    public void setRegisters(Map<String, Register> registers) {
        this.registers = registers;
    }

    private void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
        for (Register register : registerCollection) {
            regusters.put(register.getType());
        }
    }

    private void beforeMarshal(Marshaller marshaller) {
        if(null != registers) {
            registerCollection = registers.values();
        }
    }

}
bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • Thanks for your answer, Blaise. Unfortunatelly I can't use MOXy in this project and I can't change the xml. Is there any way of parsing it without the registers tag? Thanks again! – user3302039 Nov 11 '14 at 18:51
  • @user3302039 - I have updated my answer to include a potential workaround. – bdoughan Nov 11 '14 at 19:14
  • I'm trying to implement that tomorrow, so I can give a feedback. But anyway, thanks in advance! – user3302039 Nov 11 '14 at 23:50
  • Blaise, I'm sorry for the late response. My team decided to change the implementation to List, instead of Map, because of that thing you said about not being safe. But anyway, I appreciate your attention and help. Best regards! – user3302039 Nov 12 '14 at 17:46