2012-03-21 8 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オブジェクトにバインドするための標準ライブラリです(逆も同様です)。 –

答えて

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注釈はCarクラスでXmlAdapterを関連付けるために使用されます。

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

以下

の1の例でありますサブクラス。

package forum9812778; 

public class BMW extends Car { 

} 

私たちは、ツリーのルートノードを表すためにObjectを必要としています。

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> 

詳細情報

をするために:私たちは、この役割を果たすために Carsクラスを定義します3210
1

注:私はEclipseLink JAXB (MOXy)リードとJAXB 2 (JSR-222)専門家グループのメンバーです。

EclipseLink JAXB(MOXy)の@XmlDescriminatorNode/@XmlDescriminatorValue拡張を使用して、このユースケースをマップできます。

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

車:

jaxb.properties

あなたのJAXBプロバイダとしてMOXYを指定するには、次のエントリを使用して、ドメインクラスと同じパッケージにjaxb.propertiesというファイルをインクルードする必要があり

例では、継承インジケーターとしてカスタムノードを使用しています。 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>