3

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?

ngeek
  • 7,733
  • 11
  • 36
  • 42
  • I'm guessing that you can't use xpath, that you have to use jaxb, correct? – Hovercraft Full Of Eels Sep 20 '11 at 21:43
  • Hi, Thanks for this question. actually, I am also trying to do something similar but for some reason, it's not working as expected. I tried the things mentioned in this answer as well. I tried this approach and the example from the authors blog but still the JAXB Marshalling does not work as expected with `@XmlPath`. Seems like the XML produced with and without `@XmlPath` are the same. Can you please once look into this example and provide your answer: https://stackoverflow.com/questions/67500565/xmlpath-has-no-impact-during-the-jaxb-marshalling – BATMAN_2008 May 12 '21 at 10:38

3 Answers3

3

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) );
Paul Grime
  • 14,970
  • 4
  • 36
  • 58
  • Your StAX approach can be implemented using a `StreamFilter` - http://stackoverflow.com/questions/7492128/how-to-ignore-efficiently-most-part-of-an-xml-structure-when-unmarshalling-with/7493327#7493327 – bdoughan Sep 21 '11 at 00:56
3

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:

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

Community
  • 1
  • 1
bdoughan
  • 147,609
  • 23
  • 300
  • 400
0

Use XPath to select the desired element as a DOM node and unmarshal using that selected node.

forty-two
  • 12,204
  • 2
  • 26
  • 36