2017-02-19 39 views
0

Я пытаюсь прочитать XML-документ и декодировать его в Java Beans. У меня есть часть чтения, но я столкнулся с проблемой. Я в основном пытаюсь декодировать все дочерние узлы 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> 

И Разобрать его к книге Object

@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; 
     } 
    } 

класс Книга:

@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

Когда вы уже используете Джексон - это вариант для использования Джексона с расширением XML-данных для чтения XML? Или, может быть, JAXB? Использование XMLDecoder просто не будет работать здесь, поскольку оно предназначено для использования в качестве аналога XMLEncoder, который передает XML, специфичный для родовой сериализации/десериализации. –

+0

JAXB тоже можно понять, как бы я это делал?Я пытаюсь сделать это с помощью JAXB сейчас, но я все еще получаю эту глупую проблему с каталогом, когда я пытаюсь извлечь книги. – Lithicas

+0

Ну, корневой элемент вашего XML-документа не является Bok. Это каталог. И в каталоге есть книга (или, может быть, несколько, в более реалистичном примере). Поэтому создайте класс Catalog, содержащий Список . Поднимите документ в каталог (а не книгу). И получить книгу (ы) из возвращаемого объекта Catalog. TL; DR: убедитесь, что структура Java Bean соответствует структуре XML. –

ответ

1

Как уже POIN вы, безусловно, нуждаетесь в закрытом объекте Catalog. Ниже это абсолютный минимум, чтобы иметь возможность распаковать предоставленный XML-документ с помощью JAXB и извлечь книгу из него:

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. Идентификатор книги является атрибутом в документе, поэтому он должен быть объявлен как таковой, используя @XmlAttribute.
  4. @XmlElement на Catalog.books было необходимо, чтобы отразить название книги-Элементы. JAXB по умолчанию присваивает имя поля (или свойства), которое будет вместо s и, таким образом, не соответствует элементам.

Как сказал перед демонстрацией код голый минимум и должен быть изменен в соответствии с вашими потребностями (например, видимость поля, собственно конструктор, геттеры, равно, Hashcode, ToString и т.д.)

+0

Я обновил ваши предложения. Но теперь немаршал возвращает null. (Отметьте первое сообщение для обновленного кода). – Lithicas

+1

Это сработало бы, если бы вы просто скопировали и вставили демонстрационный код как есть. В обновленном коде вопроса вам также необходимо добавить @XmlAccessorType (XmlAccessType.FIELD) в класс Catalog, потому что вы добавили установщик getter * и *. JAXB может быть очень разборчивым! Изменить: используя тип доступа FIELD, никакие геттеры и сеттеры не нужны вообще, поэтому не думайте, что вам нужно добавить их только для того, чтобы сделать JAXB счастливым. –

+0

Bingo :) Спасибо за помощь! – Lithicas