简体   繁体   中英

How to model java class while parsing xml file using groovy

I have an xml file with lots of tags and subtags. I want to model that xml file in a java class. For example, for below xml file I want to create separate book class with author n title as field.

class Book{
private string title;
private String author
}

For parsing I am using the following code

def catalogue= new XmlParser().parse(file)

Book b =new Book()
b.setTitle(catalogue.book.title.text())
b.setAuthor(catalogue.book.author.text())

Sample xml file

<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
   </book>
</catalog>

My question is if the xml file contains lots of tag n subtags then manually setting the value of each class field is not a gud approach.Is there any shorter way to do this.

You can use jaxb. It uses annotations on fields. I think that you can also make jaxb create the java class from a sample xm l file.

If you have to parse many books you can iterate over the <book> tags on your XML. For example:

import groovy.transform.Canonical

@Canonical
class Book {
    String title, author
}

def text = """
<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
   </book>
   <book id="bk102">
      <author>Orwell, George</author>
      <title>1984</title>
   </book>
   <book id="bk103">
      <author>Huxley, Aldous</author>
      <title>Brave New World</title>
   </book>
</catalog>
"""

def catalog = new XmlParser().parseText(text)
def books = catalog.book.collect {
    new Book(title: it.title.text(), author: it.author.text())
}

println books

...outputs [Book(XML Developer's Guide, Gambardella, Matthew), Book(1984, Orwell, George), Book(Brave New World, Huxley, Aldous)]

Notice that I'm using the @Canonical transformation, but it's just to get a nice toString() method for free :)

Update : Sorry, I didn't notice that the Book class is in Java. I assume you cannot touch that. But still, you can parse that xml with:

def catalog = new XmlParser().parseText(text)
def books = catalog.book.collect {
    def b = new Book()
    b.setAuthor(it.author.text())
    b.setTitle(it.title.text())
    b
}

Another option, is to only set the properties on the Book object where the same named properties exist in the xml file...

So, given an xml file like this (and a java class Book as you specified in the question):

def xml = '''<catalog>
            |  <book id="bk101">
            |    <author>Gambardella, Matthew</author>
            |    <title>XML Developers Guide</title>
            |  </book>
            |  <book id="bk102">
            |    <author>Yates, Tim</author>
            |    <title>Munging XML with Groovy</title>
            |  </book>
            |</catalog>'''.stripMargin()

You can generate a list of Book objects (setting the fields that exist in the xml), like so:

def bookList = new XmlParser().parseText( xml ).with { doc ->
  doc.book.collect { xmlbook ->
    new Book().with { book ->
      xmlbook.children()*.name().intersect( Book.declaredFields.grep { !it.synthetic }.name ).each { field ->
        book.@"$field" = xmlbook."$field".text()
      }
      book
    }
  }
}

Then to print out bookList , we get:

bookList.each {
  println "Book author:$it.author, title:$it.title"
}

Which prints:

Book author:Gambardella, Matthew, title:XML Developers Guide
Book author:Yates, Tim, title:Munging XML with Groovy

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM