1

Is there any way to do mapping with single java bean for such simple xml:

<item lang="en">
   <item-url>some url</item-url>
   <parent id="id_123"/>
</item>

I've tried something like this:

@XmlRootElement( name = "item" )
public class Item {

    @XmlElement( name = "item-url" )
    private String url;

    @XmlAttribute( name = "parent/@id" )
    // Of course XPath doesn't work here, but it would be great...
    private String parentId;
}

In other words - how can I access attribute of internal element without creating of corresponding bean?

stemm
  • 5,960
  • 2
  • 34
  • 64
  • Take a look at this thread that answers your question: http://stackoverflow.com/questions/3666467/how-can-i-add-xml-attributes-to-jaxb-annotaded-class-xmlelementwrapper – Alex Sep 12 '12 at 15:02
  • @Alex, Thanks. It's a pity, but I don't use `MOXy JAXB implementation`. I don't have that annotation. I can use annotations only from package `javax.xml.bind.annotation.*` – stemm Sep 12 '12 at 15:07
  • 1
    So short answer is not that I know of. As stated in the linked SO Question, you will have to implement an XmlAdapter. So you may find easier to just add a `Parent` object with an `id` attribute. – Alex Sep 12 '12 at 15:09
  • FYI - Since your question is tagged with Java EE, if you are using WebLogic 12.1.1 (MOXy is the default JAXB provider) or GlassFish 3.1.2 (MOXy is available as a JAXB provider) then you have the MOXy JAXB implementation. I'm the MOXy lead. I have also added an answer demonstrating how this use case could be handled with any JAXB provider: http://stackoverflow.com/a/12393273/383861 – bdoughan Sep 12 '12 at 17:23
  • 1
    @Blaise Doughan, Thanks a lot! (at the moment I'm working with embedded jetty and default jaxb implementation). – stemm Sep 13 '12 at 09:00

2 Answers2

1

You could use an XmlAdapter:

ParentIdAdapter

public class ParentIdAdapter extends XmlAdapter<ParentIdAdapter.AdaptedParentId, String> {

    public String unmarshal(AdaptedParentId value) {
        return value.id;
    }

    public AdaptedParentId marshal(String value) {
        AdaptedParentId adapted = new AdaptedParentId();
        adapted.id = value;
        return adapted;
    }

    public static class AdaptedParentId {
        @XmlAttribute
        public String id;
    }

}

Item

@XmlRootElement( name = "item" )
public class Item {

    @XmlElement( name = "item-url" )
    private String url;

    @XmlElement( name = "parent" )
    @XmlJavaTypeAdapter(ParentIdAdapter.class)
    private String parentId;
}

If you are using EclipseLink MOXy as your JAXB provider then you could leverage the @XmlPath extension to do the following:

@XmlRootElement( name = "item" )
public class Item {

    @XmlElement( name = "item-url" )
    private String url;

    @XmlPath("parent/@id")
    private String parentId;
}
bdoughan
  • 147,609
  • 23
  • 300
  • 400
0

As I didn't want to create redundant classes in my package, the best solution I've found is:

@XmlRootElement( name = "item" )
public class Item {

    @XmlRootElement( name = "parent" )
    private static class ParentIdWrapper {
        @XmlAttribute( name = "id" )
        public String id;
    }

    @XmlElement( name = "item-url" )
    private String url;

    @XmlElement( name = "parent" )
    private ParentIdWrapper parentIdWrap;

    public String getParentId() {
        return this.parentIdWrap.id;
    }
}
stemm
  • 5,960
  • 2
  • 34
  • 64