javajaxbjaxb2hyperjaxb

Is it possible to use jaxb annotations to navigate objects after they are unmarshalled?


I have a fairly complex XML schema and I use hyperjaxb3 to generate pojo's with annotations for. There are times when I have the parent object and would like to check the value of a child object that may be 8 or 9 children deep. Is there anyway to use jaxb, or another tool, to get a list of child objects of a specific class based on jaxb annotations?

I could write a recursive function to search all children for an instance of a class but that would be less than ideal. Any advise would be appreciated, thanks.


Solution

  • You don't have to write the code to walk the object tree yourself — there are a few out there already (jdereg's java-util for example), and the JAXBIntrospector will find objects annotated with XmlRootElement for you. There would be a little more work required if you're looking for other annotations, but not much.

    For example:

    public static void main(String[] args) throws JAXBException {
        JAXBContext jc = JAXBContext.newInstance(Foo.class);
        JAXBIntrospector is = jc.createJAXBIntrospector();
    
        // Found objects
        List<Foo.Bar> bars = new ArrayList<>();
    
        // Object name to look for
        QName barName = new QName("", "bar");
    
        // Unmarshalled root object to introspect
        Foo target = new Foo(new Foo.Bar());
    
        // Walk the object graph looking for "bar" elements
        Traverser.traverse(target, o -> {
            if (barName.equals(is.getElementName(o))) {
                bars.add((Foo.Bar) JAXBIntrospector.getValue(o));
            }
        });
    
        System.out.println(bars);
    }
    
    //
    // Some test objects
    //
    
    @XmlRootElement(name = "foo")
    public class Foo {
        private Bar bar;
    
        public Foo() { }
    
        public Foo(Bar bar) {
            this.bar = bar;
        }
    
        @XmlElement(name="bar")
        public Bar getBar() {
            return bar;
        }
    
        public void setBar(Bar bar) {
            this.bar = bar;
        }
    
        @XmlRootElement(name="bar")
        public static class Bar {
            String name = "kate";
    
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
            }
    
            @Override
            public String toString() {
                return "Bar{name='" + name + '\'' + '}';
            }
        }
    }