How to unmarshall repeated nested classes with JAXB?

前端 未结 4 1893
故里飘歌
故里飘歌 2020-12-31 11:33

How can I instruct JAXB to process this ?

XML


 
    
 

        
相关标签:
4条回答
  • 2020-12-31 11:47

    Try this

    @XmlRootElement
    class Root {
        List<Child> allChildren = new ArrayList<Child>();
    
        private static class Parent  {
            @XmlElement
            Child child;
        }
    
        @XmlElement
        public void setParent(Parent p) {
            allChildren.add(p.child);
        }
    }
    
    0 讨论(0)
  • 2020-12-31 11:49

    You could try to use the XmlElementWrapper annotation but I am not sure how it should work with multiple wrapper nodes:

    @XmlRootElement
    public class Root {
       @XmlElementWrapper(name="parent")
       @XmlElement(name="child")
       List<Child> allChildren;
    }
    
    0 讨论(0)
  • 2020-12-31 11:53

    You will have to create a class representing the <parent> element, such as

    @XmlAccessorType(XmlAccessType.FIELD)
    public class Parent {
       @XmlElement(name="child")
       Child child;
    }
    

    You could then create a type adapter

    public class ParentToChildAdapter extends XmlAdapter<Parent, Child> {
      public Parent marshal(Child c) {
        Parent p = new Parent();
        p.child = child;
        return p;
      }
    
      public Child unmarshal(Parent p) {
        return p.child;
      }
    }
    

    and use this on the root class

    @XmlRootElement
    public class Root {
       @XmlElement(name="parent")
       @XmlJavaTypeAdapter(ParentToChildAdapter.class)
       List<Child> allChildren;
    }
    
    0 讨论(0)
  • 2020-12-31 12:12

    You could change your model and do the following:

    Root

    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Root {
       @XmlElement(name="parent")
       List<Parent> allParents;
    }
    

    Parent

    @XmlAccessorType(XmlAccessType.FIELD)
    public class Parent {
       @XmlElement(name="child")
       List<Child> allChildren;
    }
    

    UPDATE

    Is it possible to avoid the parent class ?

    There are a couple of different ways to accomplish this:

    OPTION #1 - Any JAXB Implementation using XmlAdapter

    You could use an XmlAdapter to virtually add in the Parent class.

    ChildAdapter

    import javax.xml.bind.annotation.adapters.XmlAdapter;
    
    public class ChildAdapter extends XmlAdapter<ChildAdapter.Parent, Child> {
    
        public static class Parent {
            public Child child;
        }
    
        @Override
        public Parent marshal(Child v) throws Exception {
            Parent parent = new Parent();
            parent.child = v;
            return parent;
        }
    
        @Override
        public Child unmarshal(Parent v) throws Exception {
            return v.child;
        }
    
    }
    

    Root

    The @XmlJavaTypeAdapter annotation is used to reference the XmlAdapter.

    import java.util.List;
    import javax.xml.bind.annotation.*;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    
    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Root {
    
       @XmlElement(name="parent")
       @XmlJavaTypeAdapter(ChildAdapter.class)
       List<Child> allChildren;
    
    }
    

    Child

    import javax.xml.bind.annotation.*;
    
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Child {
    
        @XmlAttribute
        int id;
    
        @XmlAttribute
        String name;
    
    }
    

    OPTION #2 - Using EclipseLink JAXB (MOXy)

    If you are using EclipseLink JAXB (MOXy) as your JAXB (JSR-222) implementation then you could do the following (Note: I'm the MOXy lead):

    Root

    import java.util.List;
    import javax.xml.bind.annotation.*;
    
    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Root {
    
       @XmlElement(name="parent")
       List<Child> allChildren;
    
    }
    

    Child

    MOXy's @XmlPath annotation works pretty much the way you are trying to use the @XmlElement annotation in your post.

    import javax.xml.bind.annotation.*;
    import org.eclipse.persistence.oxm.annotations.XmlPath;
    
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Child {
    
        @XmlPath("child/@id")
        int id;
    
        @XmlPath("child/@name")
        String name;
    
    }
    

    For More Information

    • http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
    • http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
    0 讨论(0)
提交回复
热议问题