2017-02-19 112 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