a.mcg
a.mcg

Reputation: 33

How to read XML to a list of POJOs in Java?

I'm new to XML and im trying to read in an XML page and store its contents in an arraylist.

So far i seem to have been able to get the arraylist filled with the first content, as when i tried an isEmpty, it returned false. so there is definitely containing something. However, when i try to call the overided tostring method, or even try to call any individual category for that matter, it just returns empty?

can anyone help?

heres the code im working with:

package test;

import java.io.File;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;

public class xmlmx {

   public static void main(String[] args) {
      ArrayList<Anime> list = new ArrayList<Anime>();
      try {
         File inputFile = new File("c:\\code\\ad\\XMLDB.xml");
         DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
         DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
         Document doc = dBuilder.parse(inputFile);
         doc.getDocumentElement().normalize();
         System.out.println("Root element: " + doc.getDocumentElement().getNodeName());
         NodeList nList = doc.getElementsByTagName("Anime");
         System.out.println("----------------------------");

         for (int temp = 0; temp < nList.getLength(); temp++) {
            Node nNode = nList.item(temp);
            System.out.println("\nCurrent Element :" + nNode.getNodeName());

            if (nNode.getNodeType() == Node.ELEMENT_NODE) {
               Element eElement = (Element) nNode;
               list.add(new Anime(eElement.getAttribute("ID"),
                                  eElement.getAttribute("name"),
                                  eElement.getAttribute("altname"),
                                  eElement.getAttribute("seasons"),
                                  eElement.getAttribute("episodes"),
                                  eElement.getAttribute("status"),
                                  eElement.getAttribute("DS"),
                                  eElement.getAttribute("have"),
                                  eElement.getAttribute("left"),
                                  eElement.getAttribute("plot"),
                                  eElement.getAttribute("connect"),
                                  eElement.getAttribute("image")));
               System.out.println(list.get(0).toString());
            }
         }
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
}

the arraylist is of type anime, a class here:

    package test;

class Anime{
    private String ID;
    private String name;
    private String altname;
    private String seasons;
    private String episodes;
    private String status;
    private String DS;
    private String have;
    private String left;
    private String plot;
    private String connect;
    private String image;

    public Anime(String ID, 
                 String name,
                 String altname,
                 String seasons,
                 String episodes,
                 String status,
                 String DS,
                 String have,
                 String left,
                 String plot,
                 String connect,
                 String image) {
        this.ID = ID;
        this.name = name;
        this.altname = altname;
        this.seasons = seasons;
        this.episodes = episodes;
        this.status = status;
        this.DS = DS;
        this.have = have;
        this.left = left;
        this.plot = plot;
        this.connect = connect;
        this.image = image;
    }

/*
 getters and setters here...
*/
    @Override
    public String toString() {
        return "Anime [ID=" + ID + 
               ", name=" + name + 
               ", altname=" + altname + 
               ", seasons=" + seasons + 
               ", episodes=" + episodes + 
               ", status=" + status + 
               ", DS=" + DS + 
               ", have=" + have + 
               ", left=" + left + 
               ", plot=" + plot + 
               ", connect=" + connect + 
               ", image=" + image + "]";
    }
}

finally, heres the xml:

<?xml version="1.0" encoding="UTF-8"?>
<Anime>
    <record ID="BL1">
        <name>Bleach</name>
        <altname>Burichi</altname>
        <seasons>16</seasons>
        <episodes>366</episodes>
        <status>Finished</status>
        <sound>Dubbed</sound>
        <have>All</have>
        <left>-/-</left>
        <plot>Ichigo gets grim reaper powers, fights reapers, hollows and everything in between</plot>
        <connect>Bleach movies</connect>
        <image>images/bleach.jpg</image>
    </record>
</Anime>

any help would be greatly appreciated, thank you

Upvotes: 3

Views: 2243

Answers (2)

jschnasse
jschnasse

Reputation: 9498

Use an ObjectMapper like Jackson FasterXML!

new XmlMapper().readValue(yourDataAsInputStream, Anime.class);

or for a list

new XmlMapper().readValue(yourDataAsInputStream, new TypeReference<List<Anime>>(){});

Full Example:

package stack47711679;

import java.util.List;
import org.junit.Test;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

public class HowToReadXmlToAPojoIn2017 {

    @Test
    public void readXmlToPojo() throws Exception {
        ObjectMapper mapper = new XmlMapper();
        Anime pojo = mapper.readValue(Thread.currentThread().getContextClassLoader().getResourceAsStream("47711679.xml"), Anime.class);
        System.out.println(pojo+"");
    }
    @Test
    public void readXmlToListOfPojo() throws Exception {
        ObjectMapper mapper = new XmlMapper();
        List<Anime> pojos = mapper.readValue(Thread.currentThread().getContextClassLoader().getResourceAsStream("47711679_v2.xml"), new TypeReference<List<Anime>>(){});
        System.out.println(pojos+"");
    }
}

Your POJO Anime.java

package stack47711679;

import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;

public class Anime{
    @JacksonXmlProperty(isAttribute = true)
    public String  id;
    public String name;
    public String altname;
    public String seasons;
    public String episodes;
    public String status;
    public String DS;
    public String have;
    public String left;
    public String plot;
    public String connect;
    public String image;
    public String sound;
    public Anime(){
    }

    @Override
    public String toString() {
        return "Anime [ID=" + id + 
           ", name=" + name + 
           ", altname=" + altname + 
           ", seasons=" + seasons + 
           ", episodes=" + episodes + 
           ", status=" + status + 
           ", DS=" + DS + 
           ", have=" + have + 
           ", left=" + left + 
           ", plot=" + plot + 
           ", connect=" + connect + 
           ", sound=" + sound + 
           ", image=" + image + "]";
    }
}

With Testdata:

47711679.xml

<?xml version="1.0" encoding="UTF-8"?>

<Anime id="1">
    <name>Bleach</name>
    <altname>Burichi</altname>
    <seasons>16</seasons>
    <episodes>366</episodes>
    <status>Finished</status>
    <sound>Dubbed</sound>
    <have>All</have>
    <left>-/-</left>
    <plot>Ichigo gets grim reaper powers, fights reapers, hollows and everything in between</plot>
    <connect>Bleach movies</connect>
    <image>images/bleach.jpg</image>
</Anime>

47711679_v2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Animes>
<Anime id="1">
    <name>Bleach</name>
    <altname>Burichi</altname>
    <seasons>16</seasons>
    <episodes>366</episodes>
    <status>Finished</status>
    <sound>Dubbed</sound>
    <have>All</have>
    <left>-/-</left>
    <plot>Ichigo gets grim reaper powers, fights reapers, hollows and everything in between</plot>
    <connect>Bleach movies</connect>
    <image>images/bleach.jpg</image>
</Anime>
<Anime id="2">
    <name>Something</name>
    <altname>else</altname>
    <seasons>21</seasons>
    <episodes>34</episodes>
    <status>to be continued</status>
    <sound>Dubbed</sound>
    <have>All</have>
    <left>-/-</left>
    <plot>Yes it has one</plot>
    <connect>Bleach movies</connect>
    <image>images/bleach.jpg</image>
</Anime>
</Animes>

Prints: For the list in 47711679_v2.xml:

[Anime [ID=1, name=Bleach, altname=Burichi, seasons=16, episodes=366, status=Finished, DS=null, have=All, left=-/-, plot=Ichigo gets grim reaper powers, fights reapers, hollows and everything in between, connect=Bleach movies, sound=Dubbed, image=images/bleach.jpg], Anime [ID=2, name=Something, altname=else, seasons=21, episodes=34, status=to be continued, DS=null, have=All, left=-/-, plot=Yes it has one, connect=Bleach movies, sound=Dubbed, image=images/bleach.jpg]]

And for the single entry 47711679.xml:

Anime [ID=1, name=Bleach, altname=Burichi, seasons=16, episodes=366, status=Finished, DS=null, have=All, left=-/-, plot=Ichigo gets grim reaper powers, fights reapers, hollows and everything in between, connect=Bleach movies, sound=Dubbed, image=images/bleach.jpg]

I used jackson 2.8.6.

<dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
        <version>2.8.6</version>
    </dependency>

Upvotes: -1

Sudheera
Sudheera

Reputation: 1947

Hi basically your understanding about the w3c dom xml element is wrong. "name:, "altname" etc are not attributes of "Animie" element. those are "child nodes" of "record" node. So first you have to fetch "record" node by iterating child nodes of "Animie" element. Then you can iterate through the child nodes of "record" element so that you can populate your Anime object.

Here's a simple implementation of your "xmlmx class that works. I had to use a map because you have ommitted the setter methods, this can be improved just trying to fix the xml concepts in your head.

Just replace your class with this.

package test;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;

import com.sun.org.apache.xerces.internal.dom.DeferredElementImpl;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;

public class xmlmx {

    public static void main(String[] args) {
        ArrayList<Anime> list = new ArrayList<Anime>();
        try {
            File inputFile = new File("test.xml");
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(inputFile);
            doc.getDocumentElement().normalize();
            System.out.println("Root element: " + doc.getDocumentElement().getNodeName());

            Node recordNode = null;
            NodeList childNodes = doc.getFirstChild().getChildNodes();
            for (int i = 0; i < childNodes.getLength(); i++) {
                if (childNodes.item(i).getNodeName().equals("record")) {
                    recordNode = childNodes.item(i);
                    break;
                }
            }
            System.out.println("----------------------------");


            Map<String, String> map = new HashMap<>();
            if (recordNode != null) {
                NodeList subNodes = recordNode.getChildNodes();
                for (int i = 0; i < subNodes.getLength(); i++) {
                    if (subNodes.item(i).getNodeType() == Node.ELEMENT_NODE) {
                        map.put(subNodes.item(i).getNodeName(), subNodes.item(i).getTextContent());
                    }
                }
            }

            String id = ((DeferredElementImpl) recordNode).getAttribute("ID");
            list.add(new Anime(id,
                    map.get("name"),
                    map.get("altname"),
                    map.get("seasons"),
                    map.get("episodes"),
                    map.get("status"),
                    map.get("DS"),
                    map.get("have"),
                    map.get("left"),
                    map.get("plot"),
                    map.get("connect"),
                    map.get("image")));

            System.out.println(list.get(0));


        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Upvotes: 1

Related Questions