Handling nested elements in JAXB
Asked Answered
T

4

16

I am wondering if it is possible to have JAXB not to create Java object for XML elements that serve as wrappers. For example, for XML of the following structure

<root>
    <wrapper>
        <entity/>
    </wrapper>
</root>

I do not want an object for <wrapper> to be created at all. So for a class like

class Root {
    private Entity entity;
}

the <entity> element should be unmarshalled directly into the entity field.

Is it possible to achieve with JAXB?

Tinny answered 30/6, 2010 at 9:33 Comment(6)
In your example, <wrapper> isn't going to be generated at all. Please post example code that reproduces the problem.Former
Let me rephrase it: how do I annotate provided class so that XML of the described structure can be unmarshalled to it?Pathology
That's not much better. It's still not clear what you're trying to do. We need an example.Former
If you can't understand please skip it.Pathology
I think it is confusing to say "unmarshalled", because you XML is not the result of marshaling of your entity at the first place.Ascogonium
Does JAXB have a requirement that forbids you to unmarshal XMLs produced the way whichever you want? I am pretty sure no.Pathology
T
8

Although it requires extra coding, the desired unmarshalling is accomplished in the following way using a transient wrapper object:

@XmlRootElement(name = "root")
public class Root {

    private Entity entity;

    static class Entity {

    }

    static class EntityWrapper {
        @XmlElement(name = "entity")
        private Entity entity;

        public Entity getEntity() {
            return entity;
        }
    }

    @XmlElement(name = "wrapper")
    private void setEntity(EntityWrapper entityWrapper) {
        entity = entityWrapper.getEntity();
    }

}
Tinny answered 1/7, 2010 at 7:40 Comment(2)
It seem ok but I think it reduces to just unwrapping the object i.e. assigning N properties from wrapper to new Root object. A little cumbersome solution...Harm
@MichałZiobro You're free to provide your own solution which is not cumbersomePathology
K
7

EclipseLink MOXy offers a JAXB 2.2 implementation with extensions. One of the extended capabilities is to use XPath to navigate through layers of the XML you don't want in you domain model.

If you look at:

http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/MOXyExtensions

you will notice that the Customer's name is stored within but that the name is a String attribute of Customer. This is accomplished using:

@XmlPath("personal-info/name/text()")
public String getName() {
    return name;
}

I hope this helps,

Doug

Kain answered 4/7, 2010 at 14:30 Comment(2)
Thanks for mentioning this. I was thinking about using XPath in some way, good to know there is a ready-to-use implementation.Pathology
The additional mapping flexibility of EclipseLink is great. I also really like what the developers have done with supporting XML bindings in an external mapping file instead of only through annotations. This allows a domain model to be mapped to multiple XSDs, versions, as well as different data sources without any clutterKain
S
2

Worth mentioning, if the content is a list of <entity/> instead of a single instance:

<root>
    <wrapper>
        <entity/>
        <entity/>
        ...
    </wrapper>
</root>

then you can use the @XmlElementWrapper annotation:

@XmlRootElement(name = "root")
public class Root {

    @XmlElementWrapper(name = "wrapper")
    @XmlElement(name = "entity")
    private List<Entity> entity;

    static class Entity { }

}
Snook answered 6/11, 2020 at 0:55 Comment(0)
S
-4

The whole point of JAXB or other mapping systems is to map the elements and their hierarchy to classes. In your example, you seem to want JAXB to somehow know that it can marshal entity into wrapper/entity and vice-versa without actually creating the class used for the wrapper mapping and the connection between root and entity. Which, as presented, is roughly equivalent to asking how to connect a car engine to the wheels without a driveshaft.

So, unless I am missing the point, the answer is no - neither JAXB or any other mapping program can do this. You can avoid creating classes by using something that does mapping purely dynamically (see Groovy, GPath for an example), but that avoids creating all classes, not just skipping one intermediate level in a hierarchy.

Smithsonite answered 30/6, 2010 at 9:33 Comment(2)
As explained by Doug Clarke this can be done using EclipseLink MOXy.Outgoings
This answer is so misleading. It is absolutely possible to perform the required unmarshalling - https://mcmap.net/q/736675/-handling-nested-elements-in-jaxbPathology

© 2022 - 2024 — McMap. All rights reserved.