Unmarshal to list of abstract elements

Short: I want to unmount an XML file into a list of abstract elements. I'll give some short examples: XML:

<Container>
    <Set>
        <A x="1"/>
        <B/>
        <Set>
            <C/>
            <D x="3"/>
        </Set>
        <E/>
    </Set>
</Container>

      

Java:

import java.io.File;
import java.util.List;
import javax.xml.bind.*;
import javax.xml.bind.annotation.*;

@XmlTransient
@XmlSeeAlso( {A.class, B.class, C.class, D.class, E.class, Set.class})
class Abs {

    private String x;

    public Abs() { x = null; }

    public String getX() { return x; }

    public void setX(String x) { this.x = x; }

}

@XmlRootElement(name = "A")
class A extends Abs { public A() {} }

@XmlRootElement(name = "B")
class B extends Abs { public B() {} }

@XmlRootElement(name = "C")
class C extends Abs { public C() {} }

@XmlRootElement(name = "D")
class D extends Abs { public D() {} }

@XmlRootElement(name = "E")
class E extends Abs { public E() {} }

@XmlRootElement(name = "Set")
class Set extends Abs {

    private List<Abs> elements;

    @XmlElementWrapper
    @XmlAnyElement(lax=true)
    public List<Abs> getElements() { return elements; }

    public void setElements( List<Abs> elements ) { 
        this.elements = elements;
    }

}

@XmlRootElement(name = "Container")
class Container {

    Set main;

    public Container() { this.main = null; }

    @XmlElement(name = "Set")
    Set getMain() { return main; }

    void setMain(Set main) { this.main = main; }
}

public class Main {

    public static void main(String[] args) {
        try {
        File file = new File("test.xml");
        JAXBContext jaxbContext = JAXBContext.newInstance(Container.class);
        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        Container c = (Container) jaxbUnmarshaller.unmarshal(file);

        System.out.println(c);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

      

I have a breakpoint on the print line and at this point my "c" has a null list. How can I get this to work?

+3


source to share


2 answers


Since all possible values ​​for the elements property are subclasses Abs

, I would use @XmlElementRef

.

@XmlElementRef
public List<Abs> getElements() { return elements; }

      



@XmlAnyElement(lax=true)

will give you the same behavior, but with the following restrictions:

  • An unexpected element will instantiate org.w3c.dom.Element

    and JAXB will try to put it in your List

    .
  • You won't be able to map another field / property in this class to @XmlAnyElement

    .
+2


source


Change your Set.java

to ...



import java.util.List;
import javax.xml.bind.annotation.XmlAnyElement;

public class Set extends Abs {

    private List<Object> elements;

    @XmlAnyElement(lax=true)
    public List<Object> getElements() { return elements; }

    public void setElements( List<Object> elements ) { 
        this.elements = elements;
    }

}

      

+1


source







All Articles