catch32
catch32

Reputation: 18572

how to extract attributes value from empty element - at XML parsing by DOM?

I have to parse xml file with xsd validation.

It throws java.lang.NullPointerException:

Exception in thread "main" java.lang.NullPointerException
content Carl Cracker
    at com.epam.lab.DomXmlParser.parseFromXmlToEmployee(DomParserDemo.java:103)
content 75000
    at com.epam.lab.DomParserDemo.main(DomParserDemo.java:31)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

Here is content of xml file:

<?xml version="1.0" encoding="UTF-8"?>
<staff xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="newEmployee.xsd">
    <employee>
        <name>Carl Cracker</name>
        <salary>75000</salary>
        <hiredate year="1987" month="12" day="15" />
    </employee>
    <employee>
        <name>Harry Hacker</name>
        <salary>50000</salary>
        <hiredate year="1989" month="10" day="1" />
    </employee>
    <employee>
        <name>Tony Tester</name>
        <salary>40000</salary>
        <hiredate year="1990" month="3" day="15" />
    </employee>
</staff>

And code snippet:

class DomXmlParser {

    private Schema schema;
    private Document document;
    List<Employee> empList = new ArrayList<>();

    public SchemaFactory schemaFactory;
    public final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
    public final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";



    public DomXmlParser() {  // String filename, String schemaName  - param
        try { 
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            document = builder.parse(new File(EMPLOYEE_XML.getFilename()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }    

    public List<Employee> parseFromXmlToEmployee() {

        NodeList nodeList = document.getDocumentElement().getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);

            if (node instanceof Element) {
                Employee emp = new Employee();

                NodeList childNodes = node.getChildNodes();
                for (int j = 0; j < childNodes.getLength(); j++) {
                    Node cNode = childNodes.item(j);

                    // identify the child tag of employees
                    if (cNode instanceof Element) {
                        String content = cNode.getLastChild().getTextContent().trim();
                        if (content.length() == 0) break;
                        System.out.println("content " + content);

                        switch (cNode.getNodeName()) {
                            case "name":
                                emp.setName(content);
                                break;
                            case "salary":
                                emp.setSalary(Double.parseDouble(content));
                                break;
                            case "hiredate":
                                int yearAttr = Integer.parseInt(cNode.getAttributes().getNamedItem("year").getNodeValue());
                                int monthAttr =  Integer.parseInt(cNode.getAttributes().getNamedItem("month").getNodeValue());
                                int dayAttr =  Integer.parseInt(cNode.getAttributes().getNamedItem("day").getNodeValue());

                                emp.setHireDay(yearAttr, monthAttr - 1, dayAttr);
                                break;
                        }
                    }
                }

                empList.add(emp);
            }
        }
        return empList;
    }    
}

I understand that I'm trying extract attribute from empty element, but I can't find any circumvent.

How to solve this trouble?

Upvotes: 1

Views: 1312

Answers (1)

McDowell
McDowell

Reputation: 108859

You can replace the null with an empty string when the node has no children:

String content = (cNode.hasChildNodes())
  ? cNode.getTextContent().trim()
  : "";
if (content.length() == 0) break;

However, would be better to only read the content when it makes sense to do so:

// remove content variable
emp.setName(text(cNode));

// ... later ...

private String text(Node cNode) {
  return cNode.getTextContent()
              .trim();
}

Note that it is redundant to get the Text node by calling getLastChild() when using getTextContent() on an Element.

Upvotes: 2

Related Questions