So I spent a while this morning creating an xml parser in java which is part of a job interview. I would love to have some people tear it apart so I can learn from any mistakes that I made so I can grow for future job interviews.
XML file:
<Employees> <Employee> <Name> First Last</Name> <ID> 00001 </ID></Employee><Employee> <Name> First2 Last</Name> <ID> 00002 </ID></Employee><Employee> <Name> First3 Last</Name> <ID> 00003 </ID></Employee></Employees>Java File (126 LOC)-
//@Author HunderingThoovesimport java.io.File;import java.util.Scanner;import java.util.ArrayList;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.w3c.dom.NodeList;import org.xml.sax.SAXException;import org.xml.sax.SAXParseException;public class Main { static class openXML{ private int employeeNumber; private String employeeName; void getEmployee(int i){ String[] xmlStr = xmlLoader(i); setEmployeeName(xmlStr[0]); setEmployeeNumber(xmlStr[1]); } void setEmployeeNumber(String s){ employeeNumber = Integer.parseInt(s); } void setEmployeeName(String s){ employeeName = s; } String getEmployeeName(){ return employeeName; } int getEmployeeNumber(){ return employeeNumber; } }; public static final String[] xmlLoader(int i){ String xmlData[] = new String[2]; try { int employeeCounter = i; DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); Document doc = docBuilder.parse (new File("test.xml")); // normalize text representation doc.getDocumentElement ().normalize (); NodeList listOfEmployee = doc.getElementsByTagName("Employee"); Node firstEmployeeNode = listOfEmployee.item(employeeCounter-1); int totalEmployees = listOfEmployee.getLength(); //Break xml file into parts, then break those parts down int an array by passing individual elements to srtings if(firstEmployeeNode.getNodeType() == Node.ELEMENT_NODE){ Element firstEmployeeElement = (Element)firstEmployeeNode; //------- NodeList nameList = firstEmployeeElement.getElementsByTagName("Name"); Element nameElement = (Element)nameList.item(0); NodeList textNameList = nameElement.getChildNodes(); xmlData[0]= (((Node)textNameList.item(0)).getNodeValue().trim()).toString(); //------- NodeList IDList = firstEmployeeElement.getElementsByTagName("ID"); Element IDElement = (Element)IDList.item(0); NodeList textIDList = IDElement.getChildNodes(); xmlData[1]= (((Node)textIDList.item(0)).getNodeValue().trim()).toString(); //------ }// } catch(NullPointerException npe){ System.out.println("The employee number you searched for is incorrect or does not yet exist, try again. "); String s[] = {" ", " "}; main(s); } catch (SAXParseException err) { System.out.println ("** Parsing error" + ", line " + err.getLineNumber () + ", uri " + err.getSystemId ()); System.out.println(" " + err.getMessage ()); } catch (SAXException e) { Exception x = e.getException (); ((x == null) ? e : x).printStackTrace (); } catch (Throwable t) { t.printStackTrace (); } return xmlData; } public static void main(String args[]){ openXML myXmlHandler = new openXML(); Scanner input = new Scanner(System.in); int i = -1; do{ try{ String s = ""; System.out.println("Enter the employee number that you're searching for: "); s = input.next(); try{ i= Integer.parseInt(s); } catch(NumberFormatException nfe){ i = -1;} } catch(Exception e){System.out.println("Error: " +e.getMessage());} }while(i <= 0); myXmlHandler.getEmployee(i); System.out.println("The employee Name is: " + myXmlHandler.getEmployeeName()); System.out.println("The employee Number is: " + myXmlHandler.getEmployeeNumber()); System.exit(0); } }There is one known issue in the file that I will not mention unless someone finds it, I spent about an hour trying to pin it down and the best I could do is sweep it under the rug.
3 Answers3
I just did some refactoring to your code and came up with below output.
Few points to be mentioned,
- Lets try to use OOPs concept
- Follow naming convention (also includes meaningful names for classes and methods)
- Why catch NPE (do validate your input and avoid such scenario) ?
- Try to avoid unnecessary codes (here there is no use of "System.exit(0);")
- The parsing logic can be fine tuned but this is already good for a sample program
Between good try :)And good luck with your interview.
public class XMLParserExample {static class Employee { private final int id; private final String name; public Employee(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public String getName() { return name; }}static class EmployeeXMLParser { private final Document document; public EmployeeXMLParser(String fileName) { document = loadXml(fileName); } Employee findEmployee(int index) { NodeList listOfEmployee = document.getElementsByTagName("Employee"); Node employeeNode = listOfEmployee.item(index - 1); if (employeeNode != null && employeeNode.getNodeType() == Node.ELEMENT_NODE) { String name = getElementValue((Element) employeeNode, "Name"); String id = getElementValue((Element) employeeNode, "ID"); return new Employee(Integer.parseInt(id), name); } return null; } private String getElementValue(Element parentElement, String elementName) { NodeList nodeList = parentElement.getElementsByTagName(elementName); Element element = (Element) nodeList.item(0); NodeList childNodes = element.getChildNodes(); return (((Node) childNodes.item(0)).getNodeValue().trim()).toString(); } private Document loadXml(String fileName) { DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); try { DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); Document doc = docBuilder.parse(new File(fileName)); doc.getDocumentElement().normalize(); return doc; } catch (ParserConfigurationException e) { throw new IllegalStateException("Error parsing the XML", e); } catch (SAXException e) { throw new IllegalStateException("Error parsing the XML", e); } catch (IOException e) { throw new IllegalStateException("Error accessing the XML", e); } }};void start() { EmployeeXMLParser employeeParser = new EmployeeXMLParser("test.xml"); Scanner input = new Scanner(System.in); boolean successful = false; do { System.out.println("Enter the employee number that you're searching for: "); try { Employee employee = employeeParser.findEmployee(Integer.parseInt(input.next())); if (employee == null) { printTryAgain(); } else { System.out.println("The employee Number is: " + employee.getId()); System.out.println("The employee Name is: " + employee.getName()); successful = true; } } catch (NumberFormatException nfe) { printTryAgain(); } } while (!successful);}private void printTryAgain() { System.out.println("The employee number you searched for is incorrect or does not yet exist, try again.");}public static void main(String args[]) { new XMLParserExample().start();} }- \$\begingroup\$This was a really great answer and your code is very helpful. As for the system.exit(0); It was actually because if it was removed I would get a NumberFormatException...I was wondering if you could explain why that was happening with my code? I spent a solid 30 minutes trying to figure it out.. I could catch it but I couldn't trace it.\$\endgroup\$HunderingThooves– HunderingThooves2012-04-23 16:12:52 +00:00CommentedApr 23, 2012 at 16:12
- \$\begingroup\$Strange that you got NFE. I couldn't figure out what went wrong. All I see is even if you don't use it in your program it is going to be terminated. Additional info: Never use System.exit in programs unless it is needed. System.exit normally used in batch programs to indicate whether the process/program was successfully completed. SeeSystem.exit()\$\endgroup\$Sridhar G– Sridhar G2012-04-23 23:31:38 +00:00CommentedApr 23, 2012 at 23:31
- \$\begingroup\$Try entering in a bad value (using my xml file try entering in a large number, 123451, then enter a working value when it loops.) and it will NFE without the system.exit. It's weird.\$\endgroup\$HunderingThooves– HunderingThooves2012-04-24 19:44:02 +00:00CommentedApr 24, 2012 at 19:44
Why do you have two different try blocks here? Why not join them?
do{ try{ String s = ""; System.out.println("Enter the employee number that you're searching for: "); s = input.next(); try{ i= Integer.parseInt(s); } catch(NumberFormatException nfe){ i = -1;} } catch(Exception e){System.out.println("Error: " +e.getMessage());}}while(i <= 0);I have done:
Employees emp = JAXB.read(Employees.class, filename);whereread was:
@SuppressWarnings("unchecked") public static <T> T read( Class<T> t, String filename) throws Exception { Preconditions.checkNotNull(filename); Preconditions.checkNotNull(t); java.io.File f = checkNotNull(new java.io.File(filename)); JAXBContext context = JAXBContext.newInstance(t); Unmarshaller u = context.createUnmarshaller(); return (T) u.unmarshal(f);}You can also read from stream, string or ...
I still don't like what I have written.
They are not judging if you can write code, that works. They want to see a proof that it works (tests), what has been done (jdoc documentation) and readable code.
You mustlog in to answer this question.
Explore related questions
See similar questions with these tags.

