views:

31

answers:

2

We are connecting to a third party using Jersey. We then want to extract the returned xml into our class. This is actually working fine except for one node in the xml that is in a subnode. Here is the xml returned: <response>
...
<langISO>en</langISO>
<acquirerAmount>1000</acquirerAmount>
<acquirerCurrency>GBP</acquirerCurrency> <subXml>
<authCode>122958</authCode>
</subXml>
</response>

Note that the authCode node is in a subnode (called subXml).

OurResponse myriadResponse = response.getEntity(OurResponse.class);

Here is our class, but it is not parsing out the authCode

package com.xxx;

import javax.ws.rs.Consumes;
import javax.ws.rs.Path;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@Consumes("application/xml")
public class OurResponse {
private String authCode;

@XmlElement(name = "subXml/authCode")  
public String getAuthCode() {  
    return authCode;  
}  

@XmlElement(name = "subXml/authCode")  
public void setAuthCode(String authCode) {  
    this.authCode = authCode;  
}  

}

A: 

I don't think you can annotate with XmlElement like that. You might need to create a seperate SubXml class;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="response")
public class OurResponse
{
    private String lang;
    private String amt;
    private String curr;
    private SubXml subXml;

    public OurResponse()
    {

    }

    //Getters and setters
}

and

public class SubXml
{
    private String authcode;

    public SubXml()
    {

    }

    public String getAuthcode()
    {
        return authcode;
    }

    public void setAuthcode(String authcode)
    {
        this.authcode = authcode;
    }
}

Note that the only annotation you need is @XmlRootElement on the OurResponse class and you need to set the name; name="response".

Qwerky
Unfortunately, that doesn't work for me. An OurResponse object is created and its fields are filled in, but, the subXml field is still null and (obviously) nothing is done with the authCode. (I corrected the casing of authCode to match the incoming xml).
phil
@Qwerky, if you use @XmlJavaTypeAdapter you can leverage the SubXml class to get the desired XML representation without requiring changes to your model. See http://stackoverflow.com/questions/3708532/parsing-subnodes-with-jersey/3712287#3712287
Blaise Doughan
A: 

You have a couple different options:

Option 1 - MOXy JAXB & @XmlPath

You could use the MOXy JAXB implementation and the @XmlPath extension to achieve the desired result:

import javax.xml.bind.annotation.XmlRootElement;
import org.eclipse.persistence.oxm.annotations.XmlPath;

@XmlRootElement(name="response")
public class OurResponse {
    private String authCode;

    @XmlPath("subXml/authCode/text()")
    public String getAuthCode() {
        return authCode;
    }

    public void setAuthCode(String authCode) {
        this.authCode = authCode;
    }

}

For more information see:

Option 2 - Any JAXB Impl and @XmlJavaTypeAdapter

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement(name="response")
public class OurResponse {
    private String authCode;

    @XmlJavaTypeAdapter(AuthCodeAdapter.class)
    @XmlElement(name="subXml")
    public String getAuthCode() {
        return authCode;
    }

    public void setAuthCode(String authCode) {
        this.authCode = authCode;
    }

}

with

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class AuthCodeAdapter extends XmlAdapter<SubXml, String> {

    @Override
    public String unmarshal(SubXml v) throws Exception {
        return v.getAuthCode();
    }

    @Override
    public SubXml marshal(String v) throws Exception {
        SubXml subXml = new SubXml();
        subXml.setAuthCode(v);
        return subXml;
    }

}

and

public class SubXml {

    private String authCode;

    public String getAuthCode() {
        return authCode;
    }

    public void setAuthCode(String authCode) {
        this.authCode = authCode;
    }

}

For more information see:

Blaise Doughan
Great! Thanks! Option 2 is working.
phil
Glad I could help. Since you're new to SO, once you find your answer you are encouraged to mark it as the accepted answer.
Blaise Doughan