2017-02-19 116 views
0

我正在嘗試讀取XML文檔並將其解碼爲Java Bean。我的閱讀部分已經解決,但我遇到了一個問題。我基本上試圖解碼XML文檔的所有子節點,root是「目錄」。我如何使用XMLDecoder來做到這一點?JAXB讀取XML文檔

的XMLDecoder:

private static Book jaxbXMLToObject() { 
    try { 
     JAXBContext context = JAXBContext.newInstance(Book.class); 
     Unmarshaller un = context.createUnmarshaller(); 
     Book book = (Book) un.unmarshal(new File("PATH")); 
     return book; 
    } catch (JAXBException e) { 
     e.printStackTrace(); 
    } 
    return null; 
} 

我想閱讀下列文件

<?xml version="1.0"?> 
    <catalog> 
     <book id="1"> 
      <author>Isaac Asimov</author> 
      <title>Foundation</title> 
      <genre>Science Ficition</genre> 
      <price>164</price> 
      <publish_date>1951-08-21</publish_date> 
      <description>Foundation is the first novel in Isaac Asimovs Foundation Trilogy (later expanded into The Foundation Series). Foundation is a cycle of five interrelated short stories, first published as a single book by Gnome Press in 1951. Collectively they tell the story of the Foundation, an institute to preserve the best of galactic civilization after the collapse of the Galactic Empire.</description> 
     </book> 
    </catalog> 

而在一本書對象

@XmlRootElement(name = "book") 
@XmlType(propOrder = {"id", "price", "title", "author", "genre", "description"}) 
public class Book { 
    private int id; 
    private int price; 
    private String title; 
    private String author; 
    private String genre; 
    private String description; 
    private Date publish_date; 

    public Book() { 

    } 

解析它...... 我收到錯誤:jjavax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"catalog"). Expected elements are <{}book>

如何僅使用JAXB訪問子節點?

UPDATE

目錄類:

@XmlRootElement(name = "catalog") 

    public class Catalog { 
     @XmlElement(name = "book") 
     List<Book> books; 

     public List<Book> getBooks() { 
      return books; 
     } 

     public void setBooks(List<Book> books) { 
      this.books = books; 
     } 
    } 

Book類:

@XmlAccessorType(XmlAccessType.FIELD) 
public class Book { 
    @XmlAttribute 
    int id; 
    private int price; 
    private String title; 
    private String author; 
    private String genre; 
    private String description; 
    private Date publish_date; 

    public Book() { 

    } 

    public Book(int id, int price, String title, String genre, String description, Date publicationDate) { 
     this.id = id; 
     this.price = price; 
     this.title = title; 
     this.genre = genre; 
     this.description = description; 
     this.publish_date = publicationDate; 
    } 

    public int getId() { 
     return id; 
    } 

    public int getPrice() { 
     return price; 
    } 

    public String getTitle() { 
     return title; 
    } 

    public String getGenre() { 
     return genre; 
    } 

    public String getDescription() { 
     return description; 
    } 

    public Date getPublicationDate() { 
     return publish_date; 
    } 

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

    public void setPrice(int price) { 
     this.price = price; 
    } 

    public void setTitle(String title) { 
     this.title = title; 
    } 

    public void setGenre(String genre) { 
     this.genre = genre; 
    } 

    public void setDescription(String description) { 
     this.description = description; 
    } 

    public void setPublish_date(String publish_date) { 
     this.publish_date = new Date(); 
    } 

    public String getAuthor() { 
     return author; 
    } 

    public void setAuthor(String author) { 
     this.author = author; 
    } 

    public Date getPublish_date() { 
     return publish_date; 
    } 

    public String toJSON() { 
     ObjectMapper mapper = new ObjectMapper(); 

     try { 
      return mapper.writeValueAsString(this); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     return null; 
    } 

    @Override 
    public String toString() { 
     return "Book{" + 
       "id=" + id + 
       ", price=" + price + 
       ", title='" + title + '\'' + 
       ", genre='" + genre + '\'' + 
       ", description='" + description + '\'' + 
       ", publicationDate=" + publish_date + 
       '}'; 
    } 
} 

DAO:

public class BooksDAO { 

    public BooksDAO() { 
    } 

    public List<Book> getBooks() { 
     Catalog catalog = jaxbXMLToObject(); 
     return catalog.getBooks(); 
    } 

    private static Catalog jaxbXMLToObject() { 
     try { 
      return JAXB.unmarshal(new File("PATH"), Catalog.class); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 
} 
+0

傑克遜是否可以選擇使用Jackson的XML數據格式擴展來讀取XML?或者也許JAXB?使用XMLDecoder根本無法在這裏工作,因爲它被設計爲用作XMLEncoder的對應部分,該處理器爲特定的Bean序列化/反序列化處理特定的XML。 –

+0

JAXB也是可能的,任何線索我會如何去這樣做呢?我現在試圖用JAXB來做,但當我試圖取書時,仍然會遇到這個愚蠢的目錄問題。 – Lithicas

+0

那麼,你的XML文檔的根元素不是一個Bok。這是一本目錄。目錄中有一本書(或者可能是幾本書,更爲真實的例子)。因此創建一個Catalog類,其中包含一個List 。將文檔解組到一個目錄(而不是一本書)。並從正在返回的Catalog對象中獲取書籍。 TL; DR:確保Java Bean結構與XML結構匹配。 –

回答

1

前面已經POIN通過JB Nizet,你絕對需要一個封閉的Catalog對象。以下是最低限度,以便能夠使用JAXB解組所提供的XML文檔並提取本書從它:

public class ReadXMLUsingJAXB { 

    static class Catalog { 
     @XmlElement(name = "book") 
     List<Book> books; 
    } 

    @XmlAccessorType(XmlAccessType.FIELD) 
    static class Book { 
     @XmlAttribute 
     int id; 
     String author; 
     String title; 
     String genre; 
     int price; 
     Date publish_date; 
     String description; 
    } 

    private static Book firstBookFromXML() { 
     Catalog catalog = JAXB.unmarshal(new File("PATH"), Catalog.class); 
     return catalog.books.get(0); 
    } 

    public static void main(String[] args) { 
     Book book = firstBookFromXML(); 
     System.out.println(book.id + ", " + book.author + ", " + book.title 
       + ", " + book.genre + ", " + book.price 
       + ", " + book.publish_date + ", " + book.description); 
    } 

} 

有些東西是值得一提的位置:

  1. @XmlAccessorType -Annotation不因爲只有一個字段被註釋爲@XmlElement
  2. 當選擇FIELD作爲訪問類型時,除非使用@XmlTransient註釋,否則所有字段都將被考慮,無論其可見性如何。
  3. 書籍ID是文檔中的一個屬性,因此必須使用@XmlAttribute來聲明。 Catalog.books上的
  4. @XmlElement有必要反映書籍元素的名稱。 JAXB默認爲字段(或屬性)名稱,該名稱將替代書s,因此與元素不匹配。

正如前面所說的演示代碼是最起碼的,應該當你已經在使用被改變,以適應您的需求(即現場的知名度,適當的構造,干將,平等相待,hashCode時的toString等)

+0

我已根據您的建議進行更新。但是現在解組返回null。 (檢查第一篇文章的更新代碼)。 – Lithicas

+1

如果您只是複製並粘貼演示代碼,它會起作用。在您更新的問題代碼中,您現在還需要將@XmlAccessorType(XmlAccessType.FIELD)添加到Catalog類,因爲您已添加getter *和* setter。 JAXB可以非常挑剔!編輯:使用FIELD訪問器類型根本不需要getter和setter,所以不要認爲你需要添加它們才能使JAXB快樂。 –

+0

賓果:)感謝您的幫助! – Lithicas