While JSON has become a popular choice for asynchronous communication, XML is still used for data exchange in SOAP web services. As a Spring Boot developer, you might come across a requirement to parse the XML response of a web service in your career. It is not uncommon.

In this tutorial, we will learn how to parse an XML response of a web service using DOM XML parser in Spring Boot.

DOM XML parser loads the entire data into memory and parses it into an XML document. The parsed XML document can be used to traverse different elements and nodes in any order.

Note: DOM XML parser is relatively slow and is only for parsing small XML documents as it loads a complete XML document into memory. This makes it a poor choice for parsing large XML documents. For large XML files, you should use the SAX parser. I will explain how the SAX parser works and how it is better than DOM parser in the future.

Dependencies

DOM XML parser is a part of standard Java extensions (javax) and does not require any 3rd party dependency. We only need a spring-boot-starter dependency for the Spring Boot project. Here is what our build.gradle file looks like:

build.gradle

plugins {
    id 'org.springframework.boot' version '2.1.3.RELEASE'
    id 'java'
}

apply plugin: 'io.spring.dependency-management'

group = 'com.attacomsian.xml'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
}

XML Response

Here is what our XML response looks like:

<?xml version="1.0" encoding="UTF-8" ?>
<course>
  <id>1</id>
  <title>Introduction to Spring Boot &amp; Thymeleaf</title>
  <price>49.99</price>
  <created>2019-03-15</created>
  <student>
    <id>1</id>
    <first_name>George</first_name>
    <last_name>Bluth</last_name>
    <avatar>https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg</avatar>
  </student>
  <student>
    <id>2</id>
    <first_name>Janet</first_name>
    <last_name>Weaver</last_name>
    <avatar>https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg</avatar>
  </student>
  <student>
    <id>3</id>
    <first_name>Emma</first_name>
    <last_name>Wong</last_name>
    <avatar>https://s3.amazonaws.com/uifaces/faces/twitter/olegpogodaev/128.jpg</avatar>
  </student>
</course>

We will parse the above XML response to create a Course object containing a list of Student objects.

Spring Classes

Following are the two model classes (Course & Student) we need for this example:

Student.java

package com.attacomsian.xml.models;

public class Student {

    private int id;
    private String firstName;
    private String lastName;
    private String avatar;

    public Student(int id, String firstName, String lastName, String avatar) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.avatar = avatar;
    }

     // getters and setters, equals(), toString() .... (omitted for brevity)
}

Course.java

package com.attacomsian.xml.models;

import java.util.Date;
import java.util.List;

public class Course {

    private int id;
    private String title;
    private double price;
    private Date created;
    private List<Student> students;

    public Course(int id, String title, double price, Date created) {
        this.id = id;
        this.title = title;
        this.price = price;
        this.created = created;
    }

     // getters and setters, equals(), toString() .... (omitted for brevity)
}

DOM XML Parser

We will create a Spring service named XMLService for calling our fake API. This service uses a Java DOM parser to read the XML from a remote URL and parse it into a Course object.

XMLService.java

package com.attacomsian.xml.services;

import com.attacomsian.xml.models.Course;
import com.attacomsian.xml.models.Student;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

@Service
public class XMLService {

    private final Logger logger = LoggerFactory.getLogger(XMLService.class);


    public Course parseCourse() {

        Course course = null;

        try {
            // fake endpoint that returns XML response
            String URL = "http://www.mocky.io/v2/5c8bdd5c360000cd198f831e";

            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(URL);

            // normalize XML response
            doc.getDocumentElement().normalize();

            //read course details first
            course = new Course(Integer.parseInt(doc.getElementsByTagName("id").item(0).getTextContent()),
                    doc.getElementsByTagName("title").item(0).getTextContent(),
                    Double.parseDouble(doc.getElementsByTagName("price").item(0).getTextContent()),
                    new SimpleDateFormat("yyyy-MM-dd").parse(doc.getElementsByTagName("created").item(0).getTextContent())
                    );

            //read students list
            NodeList nodeList = doc.getElementsByTagName("student");

            //create an empty list for students
            List<Student> students = new ArrayList<>();

            //loop all available student nodes
            for (int i = 0; i < nodeList.getLength(); i++) {

                Node node = nodeList.item(i);

                if(node.getNodeType() == Node.ELEMENT_NODE) {
                    Element elem = (Element) node;
                    Student student = new Student(
                            Integer.parseInt(elem.getElementsByTagName("id").item(0).getTextContent()),
                            elem.getElementsByTagName("first_name").item(0).getTextContent(),
                            elem.getElementsByTagName("last_name").item(0).getTextContent(),
                            elem.getElementsByTagName("avatar").item(0).getTextContent()
                    );
                    students.add(student);
                }
            }

            //set students in course
            course.setStudents(students);

        } catch (Exception ex) {
            logger.error(ex.getMessage());
        }

        return course;
    }
}

In parseCourse() method above, we build an instance of DocumentBuilder by using DocumentBuilderFactory. This instance parse() method is then used to send an HTTP request to the API to get the XML and parse it into a Document object. Finally, we traverse this document element and nodes to create a Course object.

Executing Application

Now let's create the main application class that implements the CommandLineRunner interface to run the Spring Boot project as a console application.

XmlParserApplication.java

package com.attacomsian.xml;

import com.attacomsian.xml.models.Course;
import com.attacomsian.xml.services.XMLService;
import org.springframework.boot.Banner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class XmlParserApplication implements CommandLineRunner {

    private XMLService xmlService;

    public XmlParserApplication(XMLService xmlService) {
        this.xmlService = xmlService;
    }

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(XmlParserApplication.class);
        // disable spring banner
        app.setBannerMode(Banner.Mode.OFF);
        app.run(args);

    }

    @Override
    public void run(String... args) throws Exception {

        // load course from XMLService
        Course course = xmlService.parseCourse();

        // print course details
        System.out.println(course);
    }
}

When the Spring Boot application is executed, you will see the following output:

Course{id=1, title='Introduction to Spring Boot & Thymeleaf', price=49.99, created=Fri Mar 15 00:00:00 PKT 2019, students=[Student{id=1, firstName='George', lastName='Bluth', avatar='https://s3.amazonaws.com/uifaces/faces/twitter/calebogden/128.jpg'}, Student{id=2, firstName='Janet', lastName='Weaver', avatar='https://s3.amazonaws.com/uifaces/faces/twitter/josephstein/128.jpg'}, Student{id=3, firstName='Emma', lastName='Wong', avatar='https://s3.amazonaws.com/uifaces/faces/twitter/olegpogodaev/128.jpg'}]}

Source code: Download the complete source code from GitHub available under MIT license.

Conclusion

In this article, I explain how to use the DOM XML parser to parse an XML response in Spring Boot. The XML can be returned by a SOAP web service or a remote XML file.

Read Next: How to read and write XML in Java

✌️ Like this article? Follow me on Twitter and LinkedIn. You can also subscribe to RSS Feed.