2013-06-11 22 views
1

隨着JAXB,我想解組包含幾個序列化對象像這樣的XML文檔:對象的Java列表而不類列表和解組XML列表

<?xml version="1.0" encoding="UTF-8"?> 
<Users> 
<User> 
    <firstName>first name value 1</firstName> 
    <lastName>last name value 1</lastName> 
    <account> 
     <expiration>expire 1</expiration> 
     <login>login 1</login> 
    </account> 
</User> 
<User> 
    <firstName>first name value 2</firstName> 
    <lastName>last name value 2</lastName> 
    <account> 
     <expiration>expire 2</expiration> 
     <login>login 2</login> 
    </account> 
</User> 
... 
</Users> 

事實是,我不想例如創建一個名爲「Users」的新類,其中包含用戶元素列表(使用@XmlWrapper註釋)。

這是我的java對象,我要轉換爲XML:

@Entity 
@Table(name="USERS") 
@XmlRootElement(name="User") 
public class User implements Serializable { 

    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    private String firstName; 
    private String lastName; 

    @OneToOne(cascade={CascadeType.REMOVE}, mappedBy="user") 
    private Account account; 

    @XmlAttribute 
    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    @XmlElement 
    public String getFirstName() { 
     return firstName; 
    } 

    public void setFirstName(String firstName) { 
     this.firstName = firstName; 
    } 

    @XmlElement 
    public String getLastName() { 
     return lastName; 
    } 

    public void setLastName(String lastName) { 
     this.lastName = lastName; 
    } 

    @XmlInverseReference(mappedBy="user") 
    @XmlElement 
    public Account getAccount() { 
     return account; 
    } 

    public void setAccount(Account account) { 
     this.account = account; 
    } 
} 

而此時我可以探微和解組只有一個XML到用戶的Java對象。像這樣:

@Test 
    public void test2() { 
     try { 
      JAXBContext jc = JAXBContext.newInstance(User.class); 
      Unmarshaller u = jc.createUnmarshaller(); 

      File f = new File("user.xml"); 
      User element = (User) u.unmarshal(f); 

      System.out.println(
        element.getAccount().getLogin() 
        ); 

     } catch (JAXBException e) { 
      e.printStackTrace(); 
     } 
    } 

我想獲得一個用戶java列表實例,而不是一個用戶實例。像這樣的例如:

List<User> elements = (List<User>) u.unmarshal(f); 

我希望這是可能的,我想知道如何;)


非常感謝您的回覆布萊斯。

我試圖讓你沒有,但我有錯誤:

java.lang.ClassCastException:com.sun.org.apache.xerces.internal.dom.ElementNSImpl不能轉換爲COM .thales.momoko.ws.model.User

下面是我的一些代碼相關部分:

public class Tools<T> { 

public List<T> getItems(Class<T> entityClass, String xmlLocation) { 
    try { 
     JAXBContext jc = JAXBContext.newInstance(Wrapper.class, entityClass.getClass()); 
     Unmarshaller unmarshaller = jc.createUnmarshaller(); 

     BufferedReader br = new BufferedReader(
       new InputStreamReader(
       this.getClass().getClassLoader().getResourceAsStream(xmlLocation))); 

     System.out.println(br.readLine()); 

     Wrapper<T> wrapper = (Wrapper<T>) unmarshaller.unmarshal(new StreamSource(br), Wrapper.class).getValue(); 

     System.out.println(wrapper); 

     return wrapper.getItems(); 

    } catch (JAXBException ex) { 
     Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, null, ex); 
    } catch (IOException ex) { 
     Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    return null; 
} 
} 

第一的println工作得很好,因爲它顯示XML文件的第一行:

<?xml version=....> 

第二的println示出了具有解組一個問題:

包裝{項= [[用戶:空],[用戶:空],[用戶:空],[用戶: null],[user:null],[user:null],[user:null],[user:null],[user:null],[user:null],[user:null] [用戶:空],[用戶:空],[用戶:空]]}

封套:

public class Wrapper<T> { 

private List<T> items = new ArrayList<>(); 

@XmlAnyElement(lax=true) 
public List<T> getItems() { 
    return items; 
} 

@Override 
public String toString() { 
    return "Wrapper{" + "items=" + items + '}'; 
} 
} 

最後的解組的電話:

@PostConstruct 
public void init() { 
    this.entityClass = User.class; 
    for (User user : (List<User>) new Tools<User>().getItems(User.class, "user.xml")) 
     System.out.println(user.getFirstName()); 
} 

它給了我在該行的錯誤與「爲」指令。

你對這個錯誤有了解嗎?

再次感謝!

編輯

解決方案:

public class Tools<T> { 

public static <T> List<T> getItems(Class<T> entityClass, String xmlLocation) { 
    try { 
     JAXBContext jc; 
     synchronized (JAXBContext.class) { 
      jc = JAXBContext.newInstance(Wrapper.class, entityClass); 
     } 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     BufferedReader br = new BufferedReader(
       new InputStreamReader(
       Import.class.getClassLoader().getResourceAsStream(xmlLocation))); 

     Wrapper<T> wrapper = (Wrapper<T>) unmarshaller.unmarshal(new StreamSource(br), Wrapper.class).getValue(); 

     return wrapper.getItems(); 

    } catch (JAXBException ex) { 
     Logger.getLogger(Import.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    return null; 
} 
} 

召喚:

@PostConstruct 
public void init() { 
    this.entityClass = User.class; 
    for (User user : (List<User>) Tools.getItems(User.class, "user.xml")) 
     em.persist(user); 
} 

回答

1

你可以使用JAXB使用StAX做到以下幾點:

import java.util.*; 
import javax.xml.bind.*; 
import javax.xml.stream.*; 
import javax.xml.transform.stream.StreamSource; 

public class Demo { 

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

     XMLInputFactory xif = XMLInputFactory.newFactory(); 
     StreamSource xml = new StreamSource("src/forum17047306/input.xml"); 
     XMLStreamReader xsr = xif.createXMLStreamReader(xml); 

     List<User> users = new ArrayList<User>(); 
     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     while(xsr.getEventType() != XMLStreamReader.END_DOCUMENT) { 
      if(xsr.isStartElement() && "User".equals(xsr.getLocalName())) { 
       User user = (User) unmarshaller.unmarshal(xsr); 
       users.add(user); 
      } 
      xsr.next(); 
     } 
     System.out.println(users.size()); 
    } 

} 

UPDATE

你可能更喜歡使用泛型列表包裝對象處理列出了以下方法: