Search code examples
javaxpathjaxbunmarshalling

Unmarshalling an XML using Xpath expression and jaxb


I am new to JAXB and would like to know if there is a way by which I can unmarshall an XML to my response object but using xpath expressions. The issue is that I am calling a third party webservice and the response which I receive has a lot of details. I do not wish to map all the details in the XML to my response object. I just wish to map few details from the xml using which I can get using specific XPath expressions and map those to my response object. Is there an annotation which can help me achieve this?

For example consider the following response

<root>
  <record>
    <id>1</id>
    <name>Ian</name>
    <AddressDetails>
      <street> M G Road </street>
    </AddressDetails>
  </record>  
</root>

I am only intrested in retrieving the street name so I want to use xpath expression to get value of street using 'root/record/AddressDetails/street' and map it to my response object

public class Response{
     // How do i map this in jaxb, I do not wish to map record,id or name elements
     String street; 

     //getter and setters
     ....
}   

Thanks


Solution

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

    You could use MOXy's @XmlPath extension for this use case.

    Response

    import javax.xml.bind.annotation.*;
    import org.eclipse.persistence.oxm.annotations.XmlPath;
    
    @XmlRootElement(name="root")
    @XmlAccessorType(XmlAccessType.FIELD)
    public class Response{
        @XmlPath("record/AddressDetails/street/text()")
        String street; 
    
        //getter and setters
    }
    

    jaxb.properties

    To use MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html)

    javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
    

    Demo

    import java.io.File;
    import javax.xml.bind.*;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            JAXBContext jc = JAXBContext.newInstance(Response.class);
    
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            File xml = new File("src/forum17141154/input.xml");
            Response response = (Response) unmarshaller.unmarshal(xml);
    
            Marshaller marshaller = jc.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(response, System.out);
        }
    
    }
    

    Output

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
       <record>
          <AddressDetails>
             <street> M G Road </street>
          </AddressDetails>
       </record>
    </root>
    

    For More Information