JAXB2: Mapping nested elements into the same Java

2019-02-23 07:40发布

问题:

I'm having trouble trying to map nested elements into the same Java class.

XML

What I'm trying to do here is to set id attribute and text element into SlideText class.

<module name="test project">
    <slide id="1">
        <layout>
            <text>hello</text>
        </layout>
    </slide>
</module>

Module class

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Module {
    @XmlAttribute
    private String  name;

    @XmlElements({
        @XmlElement(name = "slide", type = SlideText.class)
    })
    private Slide   slide;
}

Slide class

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public abstract class Slide {
    @XmlAttribute
    private String  id;
}

SlideText class

I tried using @XmlElementWrapper on text property, but I get an exception that @XmlElementWrapper can only be applied to a collection.

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class SlideText extends Slide {

    // how to map this to layout/text elements?
    private String  text;
}

Is there a way to map <layout><text>hello</text></layout> into SlideText's text property?

Thanks.

UPDATE

To illustrate what I'm trying to accomplish here, the slide can be of any type depending on what layout is used. A module knows it's a slide but it doesn't know what slide it is, which is why I have the abstract Slide class.

Essentially, if this works, I'll be creating SlideImage and SlideTextVideo that extends Slide.

Here's how the actual XML file looks like:-

<module name="test project">
    <slide id="1">
        <layout-text>
            <text>hello</text>
        </layout-text>
    </slide>
</module>
<module name="test project">
    <slide id="2">
        <layout-image>
            <image-path>img.jpg</image-path>
        </layout-image>
    </slide>
</module>
<module name="test project">
    <slide id="3">
        <layout-text-video>
            <text>hello</text>
            <video-path>a.mp4</video-path>
        </layout-text-video>
    </slide>
</module>

回答1:

If you use EclipseLink JAXB (MOXy) then you can leverage the @XmlPath extension for this (I'm the MOXy tech lead):

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class SlideText extends Slide {

    @XmlPath("layout/text/text()")
    private String  text;

}
  • http://bdoughan.blogspot.com/2010/09/xpath-based-mapping-geocode-example.html

Using standard JAXB you could leverage an XmlAdapter:

  • http://bdoughan.blogspot.com/2010/07/xmladapter-jaxbs-secret-weapon.html


回答2:

Add a new class Layout:

public class SlideText extends Slide {
    @XmlElement
    private Layout layout;
}

public class Layout {
    @XmlAttribute
    private String  text;
}


标签: java jaxb jaxb2