简体   繁体   中英

Null values for XML attribute unmarshaling

This is my xml file and it is returning null values for type and currency when unmarshalling and rest all values are getting printed. I have used unmarshalling here and all Parent and Child POOJ are specified and finally my Main method calls unmarshall function
1) Vehicle.xml

<?xml version="1.0" encoding="UTF-8"?>
<Vehicle>
   <car>
      <manufacturer>Maruti</manufacturer>
      <cost currency="INR">675000</cost>
      <name type="sedan">Ciaz</name>
      <fuelType>Petrol</fuelType>
      <driverType>Manual</driverType>
   </car>
   <car>
      <manufacturer>Maruti</manufacturer>
      <cost currency="INR">575000</cost>
      <name type="sedan">Dezire</name>
      <fuelType>Petrol</fuelType>
      <driverType>Manual</driverType>
   </car>
</Vehicle>

Respective file are as 2) Vehicle.java

package jaxb;

import java.util.List;

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

@XmlRootElement(name = "Vehicle")
public class Vehicle {

    @XmlElement
    private List<Car> car;

    public List<Car> getCar() {
        return car;
    }

    @Override
    public String toString() {
        return "Vehicle[ Car=" + car + "]";
    }

}

3) Child for POJO Car.java

package jaxb;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="Car")
public class Car {

    private String manufacturer;
    private String name;
    private String driverType;
    private String fuelType;
    private String currency;


    @XmlAttribute
    public String getCurrency() {
        return currency;
    }
    public void setCurrency(String currency) {
        this.currency = currency;
    }

    @XmlAttribute
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }


    private String type;

    private int cost;

    @XmlElement
    public String getManufacturer() {
        return manufacturer;
    }
    public void setManufacturer(String manufacturer) {
        this.manufacturer = manufacturer;
    }

    @XmlElement
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    @XmlElement
    public String getDriverType() {
        return driverType;
    }
    public void setDriverType(String driverType) {
        this.driverType = driverType;
    }

    @XmlElement
    public String getFuelType() {
        return fuelType;
    }
    public void setFuelType(String fuelType) {
        this.fuelType = fuelType;
    }

    @XmlElement
    public int getCost() {
        return cost;
    }
    public void setCost(int cost) {
        this.cost = cost;
    }


     @Override
        public String toString() {
            return "Car [name=" + name + ", fuelType=" + fuelType + ", cost=" + cost+",driverType="+driverType +",currency="+currency+ " , type="+type +"]";
        }


}

4) Fie for unmarshalling

package jaxb;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

public class VehicleJxb {

    public void unmarhalling() {

        try {
            JAXBContext jaxbContext = JAXBContext.newInstance(Vehicle.class);

            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

            Vehicle vehicle = (Vehicle) jaxbUnmarshaller.unmarshal(new File("src\\main\\java\\Data\\Vehicle.xml"));

            System.out.println(vehicle);

        } catch (JAXBException e) {

            e.printStackTrace();
        }

    }

}

5) Final Output

Vehicle[ Car=[Car [name=Ciaz, fuelType=Petrol, cost=675000,driverType=Manual,currency=null , type=null], Car [name=Dezire, fuelType=Petrol, cost=575000,driverType=Manual,currency=null , type=null]]]

With JAXB you can map attributes only on the same level. To map attributes on embedded elements you should use separate classes for these elements.

Here is how you can map attributes (publci attributes used for simplicity):

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;

@XmlRootElement(name = "Car")
public class Car {

    public static class Cost {

        @XmlValue
        public String value;

        @XmlAttribute
        public String currency;

        @Override
        public String toString() {
            return "Cost[value=" + value + ", currency=" + currency + "]";
        }

    }

    public static class Name {

        @XmlValue
        public String value;

        @XmlAttribute
        public String type;

        @Override
        public String toString() {
            return "Name[value=" + value + ", type=" + type + "]";
        }

    }

    private String manufacturer;
    private Name name;
    private String driverType;
    private String fuelType;

    @XmlAttribute
    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    private String type;

    private Cost cost;

    @XmlElement
    public String getManufacturer() {
        return manufacturer;
    }

    public void setManufacturer(String manufacturer) {
        this.manufacturer = manufacturer;
    }

    @XmlElement
    public Name getName() {
        return name;
    }

    public void setName(Name name) {
        this.name = name;
    }

    @XmlElement
    public String getDriverType() {
        return driverType;
    }

    public void setDriverType(String driverType) {
        this.driverType = driverType;
    }

    @XmlElement
    public String getFuelType() {
        return fuelType;
    }

    public void setFuelType(String fuelType) {
        this.fuelType = fuelType;
    }

    @XmlElement
    public Cost getCost() {
        return cost;
    }

    public void setCost(Cost cost) {
        this.cost = cost;
    }

    @Override
    public String toString() {
        return "Car [name=" + name + ", fuelType=" + fuelType + ", cost=" + cost + ",driverType=" + driverType + "]";
    }

}

One common approach would be to add an extra class to handle the attribute + value. If you don't want the extra indirection when using Car . You can add a shortcut getter to it.

public class Car {
    // .....

    private Money cost;

    public Money getCost() {
        return cost;
    }

    public void setCost(Money cost) {
        this.cost = cost;
    }
    /* Optional shortcut getter */
   public String getCurrency(){
     if(getCost()==null){
        return null;
     }
     return getCost().getCurrency();
   }
}

public static class Money {
    private String currency;
    private int amount;

    @XmlAttribute
    public String getCurrency() {
        return currency;
    }

    public void setCurrency(String currency) {
        this.currency = currency;
    }

    @XmlValue
    public int getAmount() {
        return amount;
    }

    public void setAmount(int cost) {
        this.amount = cost;
    }
}

try this:

@XmlAttribute(name = "cost currency")
public String getCurrency() {
    return currency;
}
@XmlAttribute(name = "name type")
public String getType() {
    return type;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM