2012-03-21 75 views
1

我有XML结构。Java实现设计问题

<cars> 
    <car name = "BMW" engine="2.5"/> 
    <car name = "Lexus" engine="4.5"/> 
    <car name = "VW" engine="1.4"/> 
    <car name = "Honda" engine="2.0"/> 
</cars> 

我有每个汽车模型的Java类。

public class BMW extends Car{ 

    public BMW(){ 


    } 


} 

如何设计我的main()类来解析此XML并自动调用所需Car的构造函数。假设我得到一个节点<。car name =“BMW”engine =“2.5”/>这意味着我想引用BMW构造函数创建一个BMW对象并将所有内容存储到列表< .Car>中。

感谢您的任何提示! :)

+2

有你看牛逼JAXB呢?它是将XML绑定到Java对象的标准库(反之亦然)。 – 2012-03-21 21:02:20

回答

1

您可以通过服用XmlAdapter的优势,使用任何JAXB (JSR-222)映射这种使用情况:

CarAdapter

在你的榜样,你正在使用的继承指标自定义节点。使用标准的JAXB API,我们可以使用XmlAdapter来映射这个用例。 XmlAdapter将域对象转换为JAXB实现(Metro,MOXy,JaxMe等)更易于映射的对象。

package forum9812778; 

import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.adapters.XmlAdapter; 

public class CarAdapter extends XmlAdapter<CarAdapter.AdaptedCar, Car> { 

    @Override 
    public AdaptedCar marshal(Car car) throws Exception { 
     AdaptedCar adaptedCar = new AdaptedCar(); 
     adaptedCar.name = car.getClass().getSimpleName(); 
     adaptedCar.engine = car.getEngine(); 
     return adaptedCar; 
    } 

    @Override 
    public Car unmarshal(AdaptedCar adaptedCar) throws Exception { 
     Car car; 
     if("BMW".equals(adaptedCar.name)) { 
      car = new BMW(); 
     } else if("Lexus".equals(adaptedCar.name)) { 
      car = new Lexus(); 
     } else if("VW".equals(adaptedCar.name)) { 
      car = new VW(); 
     } else if("Honda".equals(adaptedCar.name)) { 
      car = new Honda(); 
     } else { 
      return null; 
     } 
     car.setEngine(adaptedCar.engine); 
     return car; 
    } 

    public static class AdaptedCar { 
     @XmlAttribute 
     public String name; 

     @XmlAttribute 
     public String engine; 
    } 

} 

汽车

@XmlJavaTypeAdapter注释用于将XmlAdapterCar类关联:

package forum9812778; 

import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 

@XmlRootElement 
@XmlJavaTypeAdapter(CarAdapter.class) 
public class Car { 

    private String engine; 

    public String getEngine() { 
     return engine; 
    } 

    public void setEngine(String engine) { 
     this.engine = engine; 
    } 

} 

BMW

下面是中的一个的一个例子子类。

package forum9812778; 

public class BMW extends Car { 

} 

汽车

我们需要一个Object来表示我们的树的根节点。我们将定义Cars类担任这个角色:

package forum9812778; 

import java.util.List; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Cars { 

    private List<Car> car; 

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

    public void setCar(List<Car> car) { 
     this.car = car; 
    } 

} 

演示

package forum9812778; 

import java.io.File; 
import javax.xml.bind.*; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Cars.class); 

     File xml = new File("src/forum9812778/input.xml"); 
     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     Cars cars = (Cars) unmarshaller.unmarshal(xml); 

     for(Car car : cars.getCar()) { 
      System.out.println(car.getClass()); 
     } 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(cars, System.out); 
    } 

} 

输出

class forum9812778.BMW 
class forum9812778.Lexus 
class forum9812778.VW 
class forum9812778.Honda 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<cars> 
    <car engine="2.5" name="BMW"/> 
    <car engine="4.5" name="Lexus"/> 
    <car engine="1.4" name="VW"/> 
    <car engine="2.0" name="Honda"/> 
</cars> 

更多信息

1

注:我是EclipseLink JAXB (MOXy)铅和JAXB 2 (JSR-222)专家小组的成员。

您可以使用EclipseLink JAXB(MOXy)的@XmlDescriminatorNode/@XmlDescriminatorValue扩展名映射此用例。你需要

jaxb.properties

要指定莫西为您的JAXB提供者包括在同一封装称为jaxb.properties为您的域类具有以下项文件:

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

汽车

在您的示例中,您正在使用自定义节点作为继承指示器。您可以使用MOXy上的@XmlDescriminatorNode扩展名将其映射为name属性。我们还将使用@XmlSeeAlso注释来指定所有子类型。

package forum9812778; 

import javax.xml.bind.annotation.*; 
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorNode; 

@XmlRootElement 
@XmlDiscriminatorNode("@name") 
@XmlSeeAlso({BMW.class,Honda.class,Lexus.class,VW.class}) 
public class Car { 

    private String engine; 

    public String getEngine() { 
     return engine; 
    } 

    public void setEngine(String engine) { 
     this.engine = engine; 
    } 

} 

BMW

在每次我们需要指定,表示继承指标值的子类。这是使用MOXy的@XmlDescriminatorValue注释完成的。

package forum9812778; 

import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue; 

@XmlDiscriminatorValue("BMW") 
public class BMW extends Car { 

} 

汽车

我们需要一个对象,以表示我们的树的根节点。我们将定义级轿车服务于这个角色:

package forum9812778; 

import java.util.List; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 
public class Cars { 

    private List<Car> car; 

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

    public void setCar(List<Car> car) { 
     this.car = car; 
    } 

} 

演示

package forum9812778; 

import java.io.File; 
import javax.xml.bind.*; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(Cars.class); 

     File xml = new File("src/forum9812778/input.xml"); 
     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     Cars cars = (Cars) unmarshaller.unmarshal(xml); 

     for(Car car : cars.getCar()) { 
      System.out.println(car.getClass()); 
     } 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(cars, System.out); 
    } 

} 

输出

class forum9812778.BMW 
class forum9812778.Lexus 
class forum9812778.VW 
class forum9812778.Honda 
<?xml version="1.0" encoding="UTF-8"?> 
<cars> 
    <car name="BMW"/> 
    <car name="Lexus"/> 
    <car name="VW"/> 
    <car name="Honda"/> 
</cars> 

更多信息