JAXB读取XML文档
问题描述:
我正在尝试读取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;
}
}
答
前面已经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);
}
}
有些东西是值得一提的位置:
- 的
@XmlAccessorType
-Annotation不因为只有一个字段被注释为@XmlElement
。 - 当选择
FIELD
作为访问类型时,除非使用@XmlTransient
注释,否则所有字段都将被考虑,无论其可见性如何。 - 书籍ID是文档中的一个属性,因此必须使用
@XmlAttribute
来声明。 Catalog.books上的 -
@XmlElement
有必要反映书籍元素的名称。 JAXB默认为字段(或属性)名称,该名称将替代书s,因此与元素不匹配。
正如前面所说的演示代码是最起码的,应该当你已经在使用被改变,以适应您的需求(即现场的知名度,适当的构造,干将,平等相待,hashCode时的toString等)
杰克逊是否可以选择使用Jackson的XML数据格式扩展来读取XML?或者也许JAXB?使用XMLDecoder根本无法在这里工作,因为它被设计为用作XMLEncoder的对应部分,该处理器为特定的Bean序列化/反序列化处理特定的XML。 –
JAXB也是可能的,任何线索我会如何去这样做呢?我现在试图用JAXB来做,但当我试图取书时,仍然会遇到这个愚蠢的目录问题。 – Lithicas
那么,你的XML文档的根元素不是一个Bok。这是一本目录。目录中有一本书(或者可能是几本书,更为真实的例子)。因此创建一个Catalog类,其中包含一个List。将文档解组到一个目录(而不是一本书)。并从正在返回的Catalog对象中获取书籍。 TL; DR:确保Java Bean结构与XML结构匹配。 –