Aniruddha Raje Aniruddha Raje - 3 months ago 65
Java Question

JAXB add/remove node from existing XML

I have the following code to Create an XML and also read through it,
What I want to achieve is, remove a particular node on basis of it's ID.

Class employee.java -

package com.howtodoinjava.jaxb.examples.list;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "employee")
@XmlAccessorType (XmlAccessType.FIELD)
public class Employee
{
private Integer id;
private String firstName;
private String lastName;
private double income;

public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public double getIncome() {
return income;
}
public void setIncome(double income) {
this.income = income;
}
}


Class Employees.java -

package com.howtodoinjava.jaxb.examples.list;

import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "employees")
@XmlAccessorType (XmlAccessType.FIELD)
public class Employees
{
@XmlElement(name="employee")
private List<Employee> employees = null;

private Integer size;

public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
}


Class TestEmployeeMarshing.java -

package com.howtodoinjava.jaxb.examples.list;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class TestEmployeeMarshing
{
static Employees employees = new Employees();
static
{
employees.setEmployees(new ArrayList<Employee>());

Employee emp1 = new Employee();
emp1.setId(1);
emp1.setFirstName("John");
emp1.setLastName("Doe");
emp1.setIncome(10000.0);

Employee emp2 = new Employee();
emp2.setId(2);
emp2.setFirstName("Jane");
emp2.setLastName("Doe");
emp2.setIncome(20000.0);

Employee emp3 = new Employee();
emp3.setId(3);
emp3.setFirstName("Bacon");
emp3.setLastName("Butter");
emp3.setIncome(30000.0);

Employee emp4 = new Employee();
emp4.setId(4);
emp4.setFirstName("Pepparoni");
emp4.setLastName("Pizza");
emp4.setIncome(40000.0);

employees.getEmployees().add(emp1);
employees.getEmployees().add(emp2);
employees.getEmployees().add(emp3);
employees.getEmployees().add(emp4);
}

public static void main(String[] args) throws JAXBException
{
marshalingExample();
System.out.println("************************************************");
unMarshalingExample();
}

private static void unMarshalingExample() throws JAXBException {

JAXBContext jaxbContext = JAXBContext.newInstance(Employees.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
employees = new Employees();
employees = (Employees) jaxbUnmarshaller.unmarshal( new File("G:/xml/employees.xml") );
List<Employee> tempEmp= employees.getEmployees();


for (int i = 0; i < tempEmp.size(); i++) {

if(tempEmp.get(i).getId().equals(3)){
System.out.println("ID equals 3");
tempEmp.remove(i);
}
}

marshalingExample();

}

private static void marshalingExample() throws JAXBException
{
JAXBContext jaxbContext = JAXBContext.newInstance(Employees.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

jaxbMarshaller.marshal(employees, System.out);
jaxbMarshaller.marshal(employees, new File("G:/xml/employees.xml"));
}
}


I need to remove the Node with ID 1 and add a new Node.

Answer

You best seperate the code reading the data from code using it, e.g. by putting the parts of the code to different methods. Furthermore it would be more convenient to pass the data to the marshalling method to make it easier to reuse instead of relying on the static employees field to pass the data.

The List in a Employees instance can be modified just like any other modifiable List:

private static Employees unmarshalFromFile(String fileName) throws JAXBException {
    JAXBContext jaxbContext = JAXBContext.newInstance(Employees.class);
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
    return (Employees) jaxbUnmarshaller.unmarshal(new File(fileName));
}

private static void marshalToFile(Employees data, String fileName) throws JAXBException
{
    JAXBContext jaxbContext = JAXBContext.newInstance(Employees.class);
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

    jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    jaxbMarshaller.marshal(data, new File(fileName));
}

public static void main(String[] args) throws JAXBException {
    Employees data = unmarshalFromFile("G:/xml/employees.xml");

    Integer removeId = 1;
    data.getEmployees().removeIf((Employee emp) -> removeId.equals(emp.getId()));

    Employee newEmployee = ...
    data.getEmployees().add(newEmployee);

    marshalToFile(data, "G:/xml/employees.xml");
}

removeIf was added in java 8, but you can also do this in earlier versions by iterating through the list:

Iterator<Employee> iterator = data.getEmployees().iterator();
while (iterator.hasNext()) {
    if (removeId.equals(iterator.next().getId())) {
         iterator.remove();
    }
}