问题
I have a XML document like below and would like to perform unmarshalling against it
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sh="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<people xmlns="http://ccm.intra.bt.com/manageServiceFault/2006/06"
xmlns:cds="http://capabilities.nat.bt.com/xsd/manageServiceFault/2010/06/Contact/Details"
xmlns:sh="http://wsi.nat.bt.com/2005/06/StandardHeader/"
xsi:schemaLocation="http://ccm.intra.bt.com/manageServiceFault/2006/06 MSF_5.0.xsd">
<cds:address>
<cds:Address>
<cds:postTown>London</cds:postTown>
<cds:postCode>WC2E 7AT</cds:postCode>
<cds:thoroughfareName>Bow Street</cds:thoroughfareName>
<cds:dependentLocality>local123</cds:dependentLocality>
<cds:county>London</cds:county>
<cds:thoroughfareNumber>30-34</cds:thoroughfareNumber>
<cds:subPremise>2nd Floor</cds:subPremise>
<cds:buildingName>BT tower</cds:buildingName>
<cds:buildingNumber>Lot 1234</cds:buildingNumber>
<cds:locality>London</cds:locality>
<cds:premise>Covent Garden Exchange</cds:premise>
<cds:dependentThoroughfare>345</cds:dependentThoroughfare>
<cds:poBox>PO1234</cds:poBox>
</cds:Address>
<cds:Address>
<cds:postTown>New York</cds:postTown>
<cds:postCode>WC2E 7AT</cds:postCode>
<cds:thoroughfareName>Bow Street</cds:thoroughfareName>
<cds:dependentLocality>local123</cds:dependentLocality>
<cds:county>US</cds:county>
<cds:thoroughfareNumber>30-34</cds:thoroughfareNumber>
<cds:subPremise>2nd Floor</cds:subPremise>
<cds:buildingName>BT tower</cds:buildingName>
<cds:buildingNumber>Lot 1234</cds:buildingNumber>
<cds:locality>US</cds:locality>
<cds:premise>Covent Garden Exchange</cds:premise>
<cds:dependentThoroughfare>345</cds:dependentThoroughfare>
<cds:poBox>PO1234</cds:poBox>
</cds:Address>
<cds:country>
<cds:name>UK</cds:name>
</cds:country>
<cds:country>
<cds:name>US</cds:name>
</cds:country>
</cds:address>
</people>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Notice that element address contains one or more than one Address and Country elements. Both address and Address are same same just only the A difference. Below are my domain classes
People2.java
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlRootElement(name = "people")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(namespace = "http://capabilities.nat.bt.com/xsd/manageServiceFault/2010/06/Contact/Details")
public class People2 {
@XmlElement(name = "address")
private Addresses addresses;
public Addresses getAddresses() {
return addresses;
}
public void setAddresses(Addresses addresses) {
this.addresses = addresses;
}
}
Addresses.java
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(namespace = "http://capabilities.nat.bt.com/xsd/manageServiceFault/2010/06/Contact/Details")
public class Addresses {
@XmlElementWrapper(name = "address")
@XmlElement(name = "Address")
private List<Address> address;
@XmlElementWrapper(name = "address")
@XmlElement(name = "country")
private List<Country> country;
public Addresses() {
address = new ArrayList<Address>();
country = new ArrayList<Country>();
}
public List<Address> getAddress() {
return address;
}
public void setAddress(List<Address> address) {
this.address = address;
}
public List<Country> getCountry() {
return country;
}
public void setCountry(List<Country> country) {
this.country = country;
}
}
and below is my main code to unmarshal the XML
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
public class Demo2 {
public static void main(String[] args) throws FileNotFoundException, XMLStreamException, JAXBException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException {
XMLInputFactory xif = XMLInputFactory.newInstance();
XMLStreamReader xsr = xif.createXMLStreamReader(new FileReader("./xml/Testing2.xml"));
JAXBContext jc = JAXBContext.newInstance(People2.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
xsr.nextTag();
System.out.println("Current XML element: " + xsr.getLocalName());
xsr.nextTag();
System.out.println("Current XML element: " + xsr.getLocalName());
int tag = xsr.nextTag();
if (tag == XMLStreamConstants.START_ELEMENT) {
System.out.println("Current XML element: " + xsr.getLocalName());
People2 people = (People2) unmarshaller.unmarshal(xsr);
for (PropertyDescriptor propertyDescriptor : Introspector.getBeanInfo(People2.class, Object.class)
.getPropertyDescriptors()) {
Method method = propertyDescriptor.getReadMethod();
System.out.println("Class name: " + people.getClass().getSimpleName() + ", Method: " + method.getName()
+ ", Value: " + method.invoke(people));
}
Addresses addresses = people.getAddresses();
for (PropertyDescriptor propertyDescriptor : Introspector.getBeanInfo(Addresses.class, Object.class)
.getPropertyDescriptors()) {
Method method = propertyDescriptor.getReadMethod();
System.out.println("Class name: " + addresses.getClass().getSimpleName() + ", Method: "
+ method.getName() + ", Value: " + method.invoke(addresses));
}
}
}
}
Problem is, when printing methods in Addresses, value of getAddress and getCountry returns null like below. It seems the binding is not happening.
Current XML element: Envelope
Current XML element: Body
Current XML element: people
Class name: People2, Method: getAddresses, Value: com.bt.platform.automation.domain.Addresses@433c675d
Class name: Addresses, Method: getAddress, Value: []
Class name: Addresses, Method: getCountry, Value: []
If I remove this @XmlElementWrapper(name = "address")
in Addresses.java, it works fine like below
Current XML element: Envelope
Current XML element: Body
Current XML element: people
Class name: People2, Method: getAddresses, Value: com.bt.platform.automation.domain.Addresses@2e817b38
Class name: Addresses, Method: getAddress, Value: [com.bt.platform.automation.domain.Address@c4437c4, com.bt.platform.automation.domain.Address@433c675d]
Class name: Addresses, Method: getCountry, Value: [com.bt.platform.automation.domain.Country@3f91beef, com.bt.platform.automation.domain.Country@1a6c5a9e]
Cany anyone please help why is it not working as expected if I don't remove @XmlElementWrapper(name = "address")
? I have referred to this post - http://blog.bdoughan.com/2010/09/jaxb-collection-properties.html but it doesn't seems working for my code.
回答1:
I think you're misunderstanding what @XmlElementWrapper is used for.
For the sake of the exemple, let's say that your address element only contains Address elements.
Then you could use the following code, and remove the necessity of your Adresses class :
@XmlRootElement(name = "people")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(namespace = "http://capabilities.nat.bt.com/xsd/manageServiceFault/2010/06/Contact/Details")
public class People2 {
@XmlElement(name = "Address")
@XmlElementWrapper(name = "address")
private List<Address> addresses;
public List<Address> getAddresses() {
return addresses;
}
public void setAddresses(List<Address> addresses) {
this.addresses = addresses;
}
}
@XmlElementWrapper exists for the sake of this, as we tend to put a wrapper element around a list of given elements, and thus it would force to use an intermediary class.
来源:https://stackoverflow.com/questions/44364754/fails-to-unmarshal-list-of-xml-same-elements-having-same-name-as-parents-element