Short and sweet strongly typed XML reader for JVM.
BabyCorn XML is a library to read XML data into Java data types using XPath selector.
It could be a good configuration library because of in-built features like validator and preprocessor.
There are multiple options. Select one of the following:
<dependency>
<groupId>com.fervort.babycorn</groupId>
<artifactId>babycorn-xml</artifactId>
<version>1.0.0</version>
</dependency>
implementation 'com.fervort.babycorn:babycorn-xml:1.0.0'
In 3 quick steps:
- Add BabyCorn XML jar to your build as specified in above options.
- Create a Java class with fields and annotate it using XPath as per your XML file.
- Create an object of a java field class you have created in the last step and pass it to BabyCornXML constructor. All values will be set to field class you have created. That's All!
<?xml version="1.0" encoding="UTF-8"?>
<students>
<student>
<name>Foo Bar</name>
<rollno>11</rollno>
<division>A</division>
<lastYearGrade>78.77</lastYearGrade>
<inTopTen>yes</inTopTen>
<secretKeyNumber>922337203685477</secretKeyNumber>
<studentWeight>63.9873333</studentWeight>
<address postcode="900111" city="California"/>
<hobbies>
<hobby>Singing</hobby>
<hobby>Reading</hobby>
<hobby>Yoga</hobby>
</hobbies>
<subjects>
<subject name="Science" teacherName="Abc Pqr"/>
<subject name="Mathematics" teacherName="Lmn Opq"/>
<subject name="English" teacherName="Def Xyz"/>
</subjects>
<projects>
<project id="101">Painting</project>
<project id="102">calligraphy</project>
</projects>
</student>
</students>
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.fervort.babycorn.xml.annotation.BabyCornXMLField;
public class Students {
@BabyCornXMLField(xPath = "students/student/name")
String name;
@BabyCornXMLField(xPath = "students/student/rollno")
int rollNumber;
@BabyCornXMLField(xPath = "students/student/division")
char division;
@BabyCornXMLField(xPath = "students/student/lastYearGrade")
float lastYearGradeofStudent;
@BabyCornXMLField(xPath = "students/student/inTopTen")
boolean isStudentInTop10;
@BabyCornXMLField(xPath = "students/student/secretKeyNumber")
long secretKeyNumber;
@BabyCornXMLField(xPath = "students/student/studentWeight")
double weight;
@BabyCornXMLField(xPath = "students/student/hobbies/hobby" ,listValue = "text()")
List hobbies = new ArrayList();
@BabyCornXMLField(xPath = "students/student/subjects/subject" ,mapKey = "@name",mapValue = "@teacherName")
Map<String,String> subjects = new HashMap();
}
Create an object of a java field class you have created in the last step and pass it to BabyCornXML constructor :
public class StudentTest {
public static void main(String[] args) throws Exception {
Students students = new Students();
BabyCornXML babyCornXML = new BabyCornXML("Students.xml",students);
System.out.println("Name: "+students.name);
System.out.println("Roll Number "+students.rollNumber);
System.out.println("Division "+students.division);
System.out.println("In Top 10 "+students.isStudentInTop10);
System.out.println("last year grade "+students.lastYearGradeofStudent);
System.out.println("Weight "+students.weight);
System.out.println("SecretKey "+students.secretKeyNumber);
System.out.println("Hobbies "+students.hobbies);
System.out.println("Subjects "+students.subjects);
}
}
Name: Foo Bar
Roll Number 11
Division A
In Top 10 true
last year grade 78.77
Weight 63.9873333
SecretKey 922337203685477
Hobbies [Singing, Reading, Yoga]
Subjects {English=Def Xyz, Science=Abc Pqr, Mathematics=Lmn Opq}
If there are multiple nodes/records in the XML, you can create 2 classes, 1 for holding list of records and other one for holding fields. For example:
<teachers>
<teacher>
<name>Abc</name>
<tid>101</tid>
<department>Art</department>
</teacher>
<teacher>
<name>Pqr</name>
<tid>102</tid>
<department>Science</department>
</teacher>
<teacher>
<name>Xyz</name>
<tid>103</tid>
<department>Commerce</department>
</teacher>
</teachers>
public class Teachers {
// Note Xpath, it is teachers/teacher
@BabyCornXMLField(xPath = "teachers/teacher")
List<Teacher> teacherList = new ArrayList<Teacher>();
}
public class Teacher {
// Note Xpath, it is only name, excluding teachers/teacher
@BabyCornXMLField(xPath = "name")
public String name;
@BabyCornXMLField(xPath = "tid")
public int tid;
@BabyCornXMLField(xPath = "department")
public String department;
}
public static void main(String[] args) throws Exception {
Teachers teachers = new Teachers();
BabyCornXML babyCornXML = new BabyCornXML("Teachers.xml",teachers);
// Iterate through each teacher
for(Teacher teacher: teachers.teacherList)
{
System.out.println("name: "+teacher.name);
System.out.println("teacher id: "+teacher.tid);
System.out.println("department: "+teacher.department);
System.out.println("");
}
name: Abc
teacher id: 101
department: Art
name: Pqr
teacher id: 102
department: Science
name: Xyz
teacher id: 103
department: Commerce
Anything can be written in a XML file that can cause a program failure. To avoid such scenarios, validator can be used. You can write your own validator or use built in validators.
You can write your own validators. Here are simple steps:
- Add
@BabyCornXMLValidation(validationMethod = "validateEmployeeName")
annotation on the field. HerevalidateEmployeeName
is a java method, where validation code will be written.
public class Employees {
@BabyCornXMLValidation(validationMethod = "validateEmployeeName")
@BabyCornXMLField(xPath = "employees/employee/name")
public String name;
}
- Write a validation method
validateEmployeeName
in class Emplyees. Method should have 2 parameters as written below.
public ValidationResult validateEmployeeName(Field field, Object object)
{
String nameFromXML = (String)object;
ValidationResult result = new ValidationResult(true);
if(nameFromXML.trim().isEmpty())
{
result = new ValidationResult(false);
result.setIfInvalidMessage("Name in XML is empty");
result.setSeverity(ValidationResult.SEVERITY.STOP);
// You can use SEVERITY.CONTINUE to continue with the execution
//result.setSeverity(ValidationResult.SEVERITY.CONTINUE);
}
return result;
}
- You can get result of validation using BabyCorn XML APIs
Employees employees = new Employees();
BabyCornXML babyCornXML = new BabyCornXML("Employees.xml",employees);
Validator validator =babyCornXML.getValidator();
validator.getValidationList();
System.out.println("validation list "+validator);
Check complete example here Employees.java
Note : For field type
String,Char,Boolean
2nd method parameterobject
could be cast toString
and forDouble,float,Long
parametersobject
could be cast toDouble
before using. Return valuesetIfInvalidValue(returnValue)
should be same as type of the field.
Validator can be used to pre process the value. For example: In Employees.java example, if department is not a IT,Finance or Manufacturing
then UNKNOWN_DEPARTMENT
will be set on the field.
public ValidationResult validateDepartment(Field field, Object object)
{
String[] departments = {"IT","Finance","Manufacturing"};
String departmentFromXML = (String)object;
ValidationResult result = new ValidationResult(true);
if(!Arrays.asList(departments).contains(departmentFromXML))
{
result = new ValidationResult(false);
result.setIfInvalidValue("UNKNOWN_DEPARTMENT");
}
return result;
}
BabyCorn XML can also be used as XML DOM APIs
public void testAPIs() throws Exception
{
BabyCornXML babyCornXML = new BabyCornXML("D:\Nilesh\Students.xml");
Document doc= babyCornXML.getDocumentRoot();
NodeList nodeList = doc.getElementsByTagName("lastYearGrade");
Node node = nodeList.item(0);
System.out.println("lastYearGrade:" + node.getTextContent());
}