JAXB 解组问题(获取空列表)

JAXB Unmarshalling Issue (Getting empty list)

我正在尝试使用 JAXB api 解析以下 XML 文档,我想在其中解析包含多个 PROPERTYDATA 对象的 PROPERTYDATALIST 中的每个项目。在解组文档期间,我得到一个空列表。任何有关如何解决此问题的帮助将不胜感激。

<?xml version="1.0" encoding="UTF-8"?>
<FACILITY>
    <ARRANGEMENTACTIVITY>
        <ID>NEW</ID>
        <CUSTOMER>500000030</CUSTOMER>
        <CUSTOMERROLE>OWNER</CUSTOMERROLE>      
        <PROPERTYDATALIST>
            <PROPERTYDATA>
                <PROPERTY>FACOMMITMENT</PROPERTY>
                <AMOUNT>600000</AMOUNT>
                <TERM>5Y</TERM>
                <MATURITYDATE>20261001</MATURITYDATE>
            </PROPERTYDATA>
            <PROPERTYDATA>
                <PROPERTY>PRINCIPALINT</PROPERTY>
                <FIXEDRATE>3.5</FIXEDRATE>
            </PROPERTYDATA>         
        </PROPERTYDATALIST>
    </ARRANGEMENTACTIVITY>
</FACILITY>

下面是我写的类解组XML文件

@XmlRootElement(name = "FACILITY")
@Data
@NoArgsConstructor
@XmlAccessorType(XmlAccessType.FIELD)
public class Facility {
    @XmlElement(name = "ARRANGEMENTACTIVITY")
    private ArrangementActivity arrangementActivity;
    
}

@XmlAccessorType(XmlAccessType.NONE)
@XmlType(propOrder = {"id", "customer","propertyDataList", "application", "version", "operation"})
@Data
public class ArrangementActivity {

    @XmlElement(name = "APPLICATION")
    private String application;
    
    @XmlElement(name = "VERSION")
    private String version;
    
    @XmlElement(name = "OPERATION")
    private String operation;
    
    @XmlElement(name = "ID")
    private String id;
    
    @XmlElement(name = "CUSTOMER")
    private String customer;    
    
    @XmlElementWrapper(name = "PROPERTYDATALIST")
    @XmlElement(name = "PROPERTYDATALIST")
    private List<PropertyData> propertyDataList;    
}
@XmlAccessorType(XmlAccessType.NONE)
@Data
@XmlType(propOrder = {"property", "amount", "term", "maturityDate", "fixedRate" })
public class PropertyData {
    
    @XmlElement(name = "PROPERTY")
    private String property;
    
    @XmlElement(name = "AMOUNT")
    private String amount;
    
    @XmlElement(name = "TERM")
    private String term;
    
    @XmlElement(name = "MATURITYDATE")
    private String maturityDate;
    
    @XmlElement(name = "FIXEDRATE")
    private String fixedRate;
        
}
public class JaxbExampleMain {

    public static void main(String[] args) {
    
        String fileSourcePath = // file path";
        try {
            
            File file = new File( fileSourcePath);              
            InputStream inputStream = new FileInputStream(file); 
                
            final XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
            final Unmarshaller unmarshaller = JAXBContext.newInstance(Facility.class).createUnmarshaller();
            final Facility facility = unmarshaller.unmarshal(xmlStreamReader, Facility.class).getValue();
            System.out.println(facility.toString());

            Marshaller marshaller = JAXBContext.newInstance(Facility.class).createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            marshaller.marshal(facility, System.out);
            
            
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
}

使用上面的代码,我得到了除上面的 PropertyDataList 之外的所有元素。下面是输出


我发现你的代码有几个问题:

  1. 您已将多个根元素(ArrangementActivity、PropertyData)添加到您的 java classes。应该只有一个根元素(Facility)。

  2. 您在 proporder 中添加了一些属性,您应该包括所有属性,除非它们中的任何一个被标记为 transient

  3. 您的 XML 具有字段 capitalized 但您的字段是小写的,因此无法在 unmarshalling 期间直接分配值。您可以使用 @XmlElement 指定它将在 XML.

    中的名称
  4. (您要求的那个)您必须使用 @XmlElementWrapperXmlElement

注意:我用过Project Lombok Getter & Setter所以我没有在每个class

中使用Getter/Setter方法

以下是解组和编组您的 XML 的代码:

Facility.class

@XmlRootElement(name = "FACILITY")
@Data
@NoArgsConstructor
@XmlAccessorType(XmlAccessType.FIELD)
public class Facility {

    @XmlElement(name = "ARRANGEMENTACTIVITY")
    private ArrangementActivity arrangementActivity;
}

ArrangementActivity.class

@XmlAccessorType(XmlAccessType.NONE)
@XmlType(propOrder = {"id", "customer","propertyDataList","application","version","operation"})
@Data
public class ArrangementActivity {

    @XmlElement(name = "APPLICATION")
    private String application;

    @XmlElement(name = "VERSION")
    private String version;

    @XmlElement(name = "OPERATION")
    private String operation;

    @XmlElement(name = "ID")
    private String id;

    @XmlElement(name = "CUSTOMER")
    private String customer;

    @XmlElementWrapper(name = "PROPERTYDATALIST")
    @XmlElement(name = "PROPERTYDATA")
    private List<PropertyData> propertyDataList;
}

PropertyData.class:

@XmlAccessorType(XmlAccessType.NONE)
@Data
@XmlType(propOrder = {"property", "amount", "term", "maturityDate", "fixedRate" })
public class PropertyData {

    @XmlElement(name = "PROPERTY")
    private String property;

    @XmlElement(name = "AMOUNT")
    private String amount;

    @XmlElement(name = "TERM")
    private String term;

    @XmlElement(name = "MATURITYDATE")
    private String maturityDate;

    @XmlElement(name = "FIXEDRATE")
    private String fixedRate;
}

JaxbExampleMain.class:

public class JaxbExampleMain {
    public static void main(String[] args) throws JAXBException, XMLStreamException {
        final InputStream inputStream = Unmarshalling.class.getClassLoader().getResourceAsStream("facility.xml");
        final XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance().createXMLStreamReader(inputStream);
        final Unmarshaller unmarshaller = JAXBContext.newInstance(Facility.class).createUnmarshaller();
        final Facility facility = unmarshaller.unmarshal(xmlStreamReader, Facility.class).getValue();
        System.out.println(facility.toString());

        Marshaller marshaller = JAXBContext.newInstance(Facility.class).createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        marshaller.marshal(facility, System.out);
    }
}

以下是您得到的输出:

Facility(arrangementActivity=ArrangementActivity(application=null, version=null, operation=null, id=NEW, customer=500000030, propertyDataList=[PropertyData(property=FACOMMITMENT, amount=600000, term=5Y, maturityDate=20261001, fixedRate=null), PropertyData(property=PRINCIPALINT, amount=null, term=null, maturityDate=null, fixedRate=3.5)]))
<FACILITY>
   <ARRANGEMENTACTIVITY>
      <ID>NEW</ID>
      <CUSTOMER>500000030</CUSTOMER>
      <PROPERTYDATALIST>
         <PROPERTYDATA>
            <PROPERTY>FACOMMITMENT</PROPERTY>
            <AMOUNT>600000</AMOUNT>
            <TERM>5Y</TERM>
            <MATURITYDATE>20261001</MATURITYDATE>
         </PROPERTYDATA>
         <PROPERTYDATA>
            <PROPERTY>PRINCIPALINT</PROPERTY>
            <FIXEDRATE>3.5</FIXEDRATE>
         </PROPERTYDATA>
      </PROPERTYDATALIST>
   </ARRANGEMENTACTIVITY>
</FACILITY>