How do I parse complex XML file using DOM? - java

How do I parse complex XML file using DOM ? I need to access each child of grade but I am getting all the classes within xml files.How do I access grade , child , student and teacher elements .
public SchoolM readFileNBuildModel(String filePath) {
File file = new File(filePath);
if (file.exists()) {
AppLauncher.getLog().log(Level.INFO, " File Exist : " + filePath,filePath);
try {
AppLauncher.getLog().log(Level.INFO, " Parsing File : " + filePath,filePath);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder;
documentBuilder = dbf.newDocumentBuilder();
Document doc = documentBuilder.parse(file);
doc.getDocumentElement().normalize();
Element schoolNode = doc.getDocumentElement();
NodeList gradeList = doc.getElementsByTagName("grade");
SortedSet<GradeM> gradeSet = new TreeSet<GradeM>();
for (int temp = 0; temp < gradeList.getLength(); temp++) {
Node gradeNode = gradeList.item(temp);
Element gradeElemet = (Element) gradeNode;
GradeM gradeM = new GradeM(gradeElemet.getAttribute("id"));
SortedSet<ClassM> classSet = new TreeSet<ClassM>();
NodeList classList = doc.getElementsByTagName("classroom");
for (int classIndex = 0; classIndex < classList.getLength(); classIndex++) {
Node classNode = classList.item(classIndex);
Element classElement = (Element) classNode;
ClassM classM = new ClassM(classElement.getAttribute(CSVColumnAttributeEnum.CLASSROOM_ID.getXmlMapColumnName()),
classElement.getAttribute(CSVColumnAttributeEnum.CLASSROOM_NAME.getXmlMapColumnName()));
SortedSet<TeacherM> teacherSet = new TreeSet<TeacherM>();
SortedSet<StudentM> studentSet = new TreeSet<StudentM>();
NodeList teacherList = doc.getElementsByTagName("teacher");
NodeList studentList = doc.getElementsByTagName("student");
for (int studentIndex = 0; studentIndex < studentList.getLength(); studentIndex++) {
Node studentNode = studentList.item(studentIndex);
Element studentElement = (Element) studentNode;
if(studentElement != null){
StudentM studentM = new StudentM(studentElement.getAttribute(CSVColumnAttributeEnum.STUDENT_ID.getXmlMapColumnName()),
studentElement.getAttribute(CSVColumnAttributeEnum.STUDENT_FIRST_NAME.getXmlMapColumnName()), studentElement.getAttribute(CSVColumnAttributeEnum.STUDENT_LAST_NAME.getXmlMapColumnName()),
studentElement.getAttribute(CSVColumnAttributeEnum.STUDENT_GRADE.getXmlMapColumnName()));
studentSet.add(studentM);
}
}
for (int teacherIndex = 0; teacherIndex < teacherList.getLength(); teacherIndex++) {
Node teacherNode = teacherList.item(classIndex);
Element teacherElement = (Element) teacherNode;
if(teacherElement != null){
TeacherM teacherM = new TeacherM(teacherElement.getAttribute(CSVColumnAttributeEnum.TEACHER1_ID.getXmlMapColumnName()),
teacherElement.getAttribute(CSVColumnAttributeEnum.TEACHER1_LAST_NAME.getXmlMapColumnName()), teacherElement.getAttribute(CSVColumnAttributeEnum.TEACHER1_FIRST_NAME.getXmlMapColumnName()));
teacherSet.add(teacherM);
}
}
classM.setStudentSet(studentSet);
classM.setTeacherSet(teacherSet);
classSet.add(classM);
}
gradeM.setClassSet(classSet);
gradeSet.add(gradeM);
}
SchoolM schoolM = new SchoolM(schoolNode.getAttribute("id"), schoolNode.getAttribute("schoolName"),gradeSet);
return schoolM;
} catch (ParserConfigurationException e) {
AppLauncher.getLog().log(Level.SEVERE, " File Conversion failed because of : /n" + e.toString());
} catch (SAXException e) {
AppLauncher.getLog().log(Level.SEVERE, " File Conversion failed because of : /n" + e.toString());
} catch (IOException e) {
AppLauncher.getLog().log(Level.SEVERE, " File Conversion failed because of : /n" + e.toString());
}
}else{
AppLauncher.getLog().log(Level.WARNING, " File Does Not Exist : " + filePath,filePath);
}
return new SchoolM();
XML Files:
<grade id="1">
<classroom id="101" name="Mrs. Jones' Math Class">
<teacher id="10100000001" first_name="Barbara" last_name="Jones"/>
<student id="10100000010" first_name="Michael" last_name="Gil"/>
<student id="10100000011" first_name="Kimberly" last_name="Gutierrez"/>
<student id="10100000013" first_name="Toby" last_name="Mercado"/>
<student id="10100000014" first_name="Lizzie" last_name="Garcia"/>
<student id="10100000015" first_name="Alex" last_name="Cruz"/>
</classroom>
<classroom id="102" name="Mr. Smith's PhysEd Class">
<teacher id="10200000001" first_name="Arthur" last_name="Smith"/>
<teacher id="10200000011" first_name="John" last_name="Patterson"/>
<student id="10200000010" first_name="Nathaniel" last_name="Smith"/>
<student id="10200000011" first_name="Brandon" last_name="McCrancy"/>
<student id="10200000012" first_name="Elizabeth" last_name="Marco"/>
<student id="10200000013" first_name="Erica" last_name="Lanni"/>
<student id="10200000014" first_name="Michael" last_name="Flores"/>
<student id="10200000015" first_name="Jasmin" last_name="Hill"/>
<student id="10200000016" first_name="Brittany" last_name="Perez"/>
<student id="10200000017" first_name="William" last_name="Hiram"/>
<student id="10200000018" first_name="Alexis" last_name="Reginald"/>
<student id="10200000019" first_name="Matthew" last_name="Gayle"/>
</classroom>
<classroom id="103" name="Brian's Homeroom">
<teacher id="10300000001" first_name="Brian" last_name="O'Donnell"/>
</classroom>
</grade>

Use the getElementsByTagName method on the element you are processing e.g. use gradeElemet.getElementByTagName("classroom") instead of doc.getElementsByTagName("classroom"). Then inside all of your nested loops continue that approach to call the method on the currently processed element and not on the complete document.

Related

How to read a specific XML node with a given value in Java

Given an XML content like below.
Is there an API that can return the whole student node when I pass just the value of rollno. For e.g., If I pass 493 then I should get the student info for 493 with all child elements like firstname, lastname,.. marks etc
<?xml version = "1.0"?>
<class>
<old>
<student rollno = "393">
<firstname>dinkar</firstname>
<lastname>kad</lastname>
<nickname>dinkar</nickname>
<marks>85</marks>
</student>
<student rollno = "493">
<firstname>Vaneet</firstname>
<lastname>Gupta</lastname>
<nickname>vinni</nickname>
<marks>95</marks>
</student>
</old>
<current>
<student rollno = "593">
<firstname>jasvir</firstname>
<lastname>singn</lastname>
<nickname>jazz</nickname>
<marks>90</marks>
</student>
<student rollno = "125">
<firstname>abcd</firstname>
<lastname>defc</lastname>
<nickname>dumy</nickname>
<marks>90</marks>
</student>
<student rollno = "965">
<firstname>xyz</firstname>
<lastname>defc</lastname>
<nickname>sample</nickname>
<marks>90</marks>
</student>
</current>
</class>
Not sure about getting the whole set with one call, but you can get the value for each tag...something like:
File fXmlFile = new File("student.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("student");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
System.out.println("Student rollno : "
+ eElement.getAttribute("rollno"));
System.out.println("Firstname : "
+ eElement.getElementsByTagName("firstname")
.item(0).getTextContent());
System.out.println("Last Name : "
+ eElement.getElementsByTagName("lastname")
.item(0).getTextContent());
System.out.println("Nickname : "
+ eElement.getElementsByTagName("nickname")
.item(0).getTextContent());
System.out.println("Marks : "
+ eElement.getElementsByTagName("marks")
.item(0).getTextContent());
}
}

Parsing xml using Dom4j based on condition

I have the following XMLfile that i need to parse through and i need to select the firstname of the student whose person_type value=1. I am using dom4j in my java project and i am not able to find a solution to extract the firstname based on the value of the person_type. Any help would be appreciated.
<?xml version="1.0"?>
<class>
<student>
<firstname>dinkar</firstname>
<lastname>kad</lastname>
<nickname>dinkar</nickname>
<marks>85</marks>
<person_types>
<person_type>1</person_type>
<person_description>POC</person_description>
</person_types>
</student>
<student>
<firstname>Vaneet</firstname>
<lastname>Gupta</lastname>
<nickname>vinni</nickname>
<marks>95</marks>
<person_types>
<person_type>1</person_type>
<person_description>Assistant</person_description>
</person_types>
</student>
<student>
<firstname>jasvir</firstname>
<lastname>singn</lastname>
<nickname>jazz</nickname>
<marks>90</marks>
<person_types>
<person_type>1</person_type>`
<person_description>Leader</person_description>
</person_types>
</student>
</class>
public static void main(String[] args) {
try {
File inputFile = new File("input.txt");
SAXReader reader = new SAXReader();
Document document = reader.read( inputFile );
System.out.println("Root element :"
+ document.getRootElement().getName());
Element classElement = document.getRootElement();
List<Node> nodes = document.selectNodes("/class/student" );
System.out.println("----------------------------");
for (Node node : nodes) {
if("1".equals(node.selectSingleNode("person_types").selectSingleNode("person_type").getText())){
System.out.println("\nCurrent Element :"
+ node.getName());
System.out.println("Student roll no : "
+ node.valueOf("#rollno") );
System.out.println("First Name : " + node.selectSingleNode("firstname").getText());
System.out.println("Last Name : " + node.selectSingleNode("lastname").getText());
System.out.println("First Name : " + node.selectSingleNode("nickname").getText());
System.out.println("Marks : " + node.selectSingleNode("marks").getText());
}
}
} catch (DocumentException e) {
e.printStackTrace();
}
}

How to read a generic XML file in java

I'm looking for ways to read a generic xml file
Here is an example of a normal xml file
<?xml version="1.0"?>
<students>
<student>
<name>John</name>
<grade>B</grade>
<age>12</age>
</student>
<student>
<name>Mary</name>
<grade>A</grade>
<age>11</age>
</student>
<student>
<name>Simon</name>
<grade>A</grade>
<age>18</age>
</student>
</students>
and here is example of a typical xml parser that would read that code and print it out
public class XMLParser {
public void getAllUserNames(String fileName) {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
File file = new File(fileName);
if (file.exists()) {
Document doc = db.parse(file);
Element docEle = doc.getDocumentElement();
// Print root element of the document
System.out.println("Root element of the document: "
+ docEle.getNodeName());
NodeList studentList = docEle.getElementsByTagName("student");
// Print total student elements in document
System.out
.println("Total students: " + studentList.getLength());
if (studentList != null && studentList.getLength() > 0) {
for (int i = 0; i < studentList.getLength(); i++) {
Node node = studentList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
System.out
.println("=====================");
Element e = (Element) node;
NodeList nodeList = e.getElementsByTagName("name");
System.out.println("Name: "
+ nodeList.item(0).getChildNodes().item(0)
.getNodeValue());
nodeList = e.getElementsByTagName("grade");
System.out.println("Grade: "
+ nodeList.item(0).getChildNodes().item(0)
.getNodeValue());
nodeList = e.getElementsByTagName("age");
System.out.println("Age: "
+ nodeList.item(0).getChildNodes().item(0)
.getNodeValue());
}
}
} else {
System.exit(1);
}
}
} catch (Exception e) {
System.out.println(e);
}
}
public static void main(String[] args) {
XMLParser parser = new XMLParser();
parser.getAllUserNames("c:\\test.xml");
}
}
This code needs lines like this
NodeList studentList = docEle.getElementsByTagName("student");
NodeList nodeList = e.getElementsByTagName("name");
In order to work correctly.
My questions comes from how would I make that generic. Is there any way where I could read that same XML file without having to get specific elements by tagNames and yet still print it out in a view able format.
In the above example you are using Dom parser. By using Jaxb Context unmarshaller you can convert the xml to java object, then you can achive your task.
You need to have a generic function to handle.
Generic function is as follows:
/* Prints the Node Value */
public void PrintNodeValue(Element element, String tagName, String msg)
{
NodeList nodeList = element.getElementsByTagName(tagName);
System.out.println(msg + nodeList.item(0).getChildNodes().item(0).getNodeValue());
}
Function is called as below:
PrintNodeValue(e, "name", "Name: ");
PrintNodeValue(e, "grade", "Grade: ");

Read values from a complex xml using java

HI I am new to Java and trying to read an XML file.
Here is my XML file :-
<?xml version="1.0" encoding="UTF-8"?>
<parameter>
<attribute>a</attribute>
Here is my code I am trying to read the key and value from the xml but I am stuck .Here is my code :-
public class TestDBMain {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
File file = new File("ACL.xml");
DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbfactory.newDocumentBuilder();
Document doc = builder.parse(file);
NodeList nList = doc.getElementsByTagName("testCaseDataName");
for(int i = 0;i<nList.getLength();i++){
Node nNode = nList.item(i);
if(nNode.getNodeType()== Node.ELEMENT_NODE){
Element ele = (Element) nNode;
// System.out.println(ele.getTextContent());
//System.out.println(ele.getElementsByTagName("testCaseName").item(0).getTextContent());
System.out.println(ele.getAttributeNode("testCaseDataName"));
//I dont know which methods to use to print the key and value in the xml under parameter
}
}
}
}
Can anyone please help me with this
Disclaimer: I maintain the JDOM project, so I am biased.... but... this is an ideal use case for JDOM:
Document doc = new SAXBuilder().build(new File("ACL.xml"));
Element root = doc.getRootElement();
for (Element testcase : root.getChildren()) {
int id = Integer.parseInt(testcase.getChildText("id"));
String name = testcase.getChildText("testCaseName");
String expect = testcase.getChildText("expectedResult");
Map<String,String> params = new LinkedHashMap<String,String>();
Element parmemt = testcase.getChild("parameter");
if (parmemt != null) {
Iterator<Element> it = parmemt.getChildren().iterator();
while (it.hasNext()) {
Element key = it.next();
if (!"key".equals(key.getName())) {
throw new IllegalStateException("Expected key but got " + key);
}
if (!it.hasNext()) {
throw new IllegalStateException("Expected value for key " + key);
}
Element val = it.next();
if (!"value".equals(val.getName())) {
throw new IllegalStateException("Expected value but got " + val);
}
params.put(key.getValue(), val.getValue());
}
}
System.out.printf("Processing test case %d -> %s\n Expect %s\n Parameters: %s\n",
id, name, expect, params.toString());
}
For me this produces the output
Processing test case 1 -> EditTest
Expect nooptionsacltrue
Parameters: {}
Processing test case 2 -> AddTest
Expect featuresaddedacltrue
Parameters: {featues=w,f}
Processing test case 3 -> AddTest
Expect duplicateacltrue
Parameters: {projectType=NEW, Name=28HPM, status=ACTIVE, canOrder=Yes}
your code read <testCaseDataName> node. it is not go inside of this tag.
so try this..
for(int i = 0;i<nList.getLength();i++){
NodeList nodeList = nList.item(i).getChildNodes();
for(int j = 0;j<nList.getLength();j++){
Node nNode = nodeList.item(j);
if(nNode.getNodeType()== Node.ELEMENT_NODE){
System.out.println(nNode.getNodeName() +" : "+nNode.getTextContent());
if(nNode.getNodeName().equals("parameter")){
NodeList param = nNode.getChildNodes();
System.out.println(" "+param.item(0).getNodeName() +" : "+param.item(0).getTextContent());
System.out.println(" "+param.item(1).getNodeName() +" : "+param.item(1).getTextContent());
}
}
}
}

java xml dom parsing

I have this project I'm working on where I want to parse an xml file that looks like this:
<?xml version='1.0' encoding='UTF-8'?>
<projectlist>
<project>
<name>SuperDuperApp</name>
<type>batch</type>
<prod>
<server>testserver01</server>
</prod>
<qa>
<server>testserver01</server>
</qa>
<dev>
<server>testserver01</server>
</dev>
</project>
<project>
<name>Calculator</name>
<type>deploy</type>
<prod>
<server>testserver02</server>
<server>testserver03</server>
<server>testserver04</server>
</prod>
<qa>
<server>testserver05</server>
<server>testserver06</server>
<server>testserver07</server>
</qa>
<dev>
<server>testserver12</server>
<server>testserver13</server>
<server>testserver14</server>
</dev>
</project>
</projectlist>
With this method parsing the file and trying to print out in the format:
name: SuperDuperApp
type: batch
server: testserver01
name: Calculator
type: deploy
environment: dev
server: testserver12
server: testserver13
server: testserver14
etc.
public void parseXML() {
ArrayList al = new ArrayList();
HashSet hs = new HashSet();
try {
InputStream file = this.getClass().getResourceAsStream(
"/net/swing/sandbox/util/config/projectlist.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(file);
doc.getDocumentElement().normalize();
System.out.println("Root element: " + doc.getDocumentElement().getNodeName());
NodeList nList = doc.getElementsByTagName("project");
System.out.println("Information of all servers...");
for (int i=0;i<nList.getLength();i++){
Node fstNode = nList.item(i);
if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
Element fstElement = (Element) fstNode;
NodeList nameElementList = fstElement.getElementsByTagName("name");
Element nameElement = (Element) nameElementList.item(0);
NodeList name = nameElement.getChildNodes();
System.out.println("project name: " + ((Node) name.item(0)).getNodeValue());
hs.add(((Node) name.item(0)).getNodeValue());
NodeList typeElementList = fstElement.getElementsByTagName("type");
Element typeElement = (Element) typeElementList.item(0);
NodeList type = typeElement.getChildNodes();
System.out.println("Deploy type: " + ((Node) type.item(0)).getNodeValue());
//print out server list can't do it for some reason
}
}
} catch (Exception e) {
e.printStackTrace();
}
try {
al.clear();
al.addAll(hs);
Collections.sort(al);
for (int z = 0; z < al.size(); z++) {
listModel.addElement(al.get(z));
}
} catch (Exception e) {
e.printStackTrace();
}
lstProject.validate();
}
So I rewrote my method and now I'm just stuck <---newb
Check the documentation for Node. Each node has a method getChildNodes. Check that for the existence of children nodes and than iterate over them like you are doing.
If your xml was created using an xsd schema, you could instead use JAXB to create classes for it, using the xjc tool. That should make your life a bit easier.
I think it's appropriate to use XSLT transform in your case (much less boilerplate code) Look at TransformerFactory and java api for xml processing.
As a q&d solution you could apply the same strategy as for getting "project" node:
...
System.out.println("servers:");
NodeList sList = eElement.getElementsByTagName("server");
for (int i = 0; i < sList.getLength(); i++) {
String stuff = sList.item(i).getFirstChild().getNodeValue();
System.out.println(stuff);
}

Categories