未能解组具有相同的名称作为父母XML元素相同的元素列表中使用@XmlElementWrapper

问题描述:

我有一个XML文档,如下图所示,并想进行解组反对未能解组具有相同的名称作为父母XML元素相同的元素列表中使用@XmlElementWrapper

<?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> 

注意元素地址包含一个或多个比一个地址和国家元素。地址和地址都相同,只是A区别。下面是我的领域类

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; 
    } 

} 

以下是我的主要代码来解组​​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)); 

      } 

     } 
    } 

} 

问题是,当在地址中打印方法,getAddress和getCountry的值如下所示返回null。看起来绑定没有发生。

Current XML element: Envelope 
Current XML element: Body 
Current XML element: people 
Class name: People2, Method: getAddresses, Value: [email protected] 
Class name: Addresses, Method: getAddress, Value: [] 
Class name: Addresses, Method: getCountry, Value: [] 

如果我删除此@XmlElementWrapper(name = "address")在Addresses.java,它工作正常,像下面

Current XML element: Envelope 
Current XML element: Body 
Current XML element: people 
Class name: People2, Method: getAddresses, Value: [email protected] 
Class name: Addresses, Method: getAddress, Value: [[email protected], [email protected]] 
Class name: Addresses, Method: getCountry, Value: [[email protected], [email protected]] 

藤请人帮忙为什么它并不如预期,如果我不删除@XmlElementWrapper(name = "address")工作?我已经提到这个帖子 - http://blog.bdoughan.com/2010/09/jaxb-collection-properties.html,但它似乎并没有为我的代码工作。

我认为你误解了@XmlElementWrapper的用途。

为了举例,假设您的地址元素只包含地址元素。

然后,你可以使用下面的代码,并删除你不会忽略类的必要性:

@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存在的这个缘故,因为我们往往把包装元素围绕一个列表给出元素,因此它会强制使用中介类。