Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to ignore (efficiently) most part of an XML structure when unmarshalling with JAXB?

When processing a web service response with a quite complex XML structure, I am only interested with a very small subset of information. Lets consider the using JAXB has to be used in this context.

As an example, lets say I am only interested in retrieving d (which can be modeled as a single JAXB bean):

a
  b1
    c1
    c2
  b2
    d

What is the fastest recommended way to ignore everything else but retrieve d?

like image 394
ngeek Avatar asked Jan 18 '26 14:01

ngeek


2 Answers

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.

There are a couple of different ways that you could handle this use case:

Option #1 - StreamFilter Any JAXB Implementation

You could use a StAX XMLStreamReader with a StreamFilter to filter out the portions of the XML document that you don't wish to map to:

  • JAXB filtered parsing

Option #2 - @XmlPath in MOXy JAXB

You could use the @XmlPath extension in MOXy:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class A {

    @XmlPath("b2/d/text()")
    private String d;

}

For More Information

  • http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
  • http://blog.bdoughan.com/2010/09/xpath-based-mapping-geocode-example.html
  • http://blog.bdoughan.com/2011/03/map-to-element-based-on-attribute-value.html
  • http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
like image 98
bdoughan Avatar answered Jan 21 '26 05:01

bdoughan


I think the fastest way would depend on exactly how the xml is formatted. E.g. you could create your own InputStream that wraps the real InputStream and just be on the lookout for "<d>" to trigger you to start passing data through to jaxb.

e.g.

   InputStream is = // get real stream
   JAXBContext jc = JAXBContext.newInstance( "com.acme.foo" );
   Unmarshaller u = jc.createUnmarshaller();
   Object o = u.unmarshal( new MySpecialStream(is) );

If you needed a more xml-like approach then you could create your own XMLStreamReader that only passed on certain calls if you were inside a d element.

e.g.

   JAXBContext jc = JAXBContext.newInstance( "com.acme.foo" );
   Unmarshaller u = jc.createUnmarshaller();
   XMLStreamReader xsr = XMLInputFactory.newInstance().createXMLStreamReader( ... );
   Object o = u.unmarshal( new MyXSRWrapper(xsr) );
like image 45
Paul Grime Avatar answered Jan 21 '26 05:01

Paul Grime



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!