问题
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;
}
}
回答1:
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:
- http://bdoughan.blogspot.com/2010/09/xpath-based-mapping-geocode-example.html
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:
- http://bdoughan.blogspot.com/2010/07/xmladapter-jaxbs-secret-weapon.html
回答2:
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".
来源:https://stackoverflow.com/questions/3708532/parsing-subnodes-with-jersey