有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在DOM解析XML时从空元素中提取属性值?

我必须用xsd验证来解析xml文件

它抛出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)

以下是xml文件的内容:

<?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>

和代码段:

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;
    }    
}

我知道我正在尝试从空元素中提取属性,但我找不到任何规避方法

如何解决这个问题


共 (1) 个答案

  1. # 1 楼答案

    当节点没有子节点时,可以将null替换为空字符串:

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

    但是,最好仅在有意义的情况下阅读内容:

    // remove content variable
    emp.setName(text(cNode));
    
    // ... later ...
    
    private String text(Node cNode) {
      return cNode.getTextContent()
                  .trim();
    }
    

    请注意,在元素上使用getTextContent()时,通过调用getLastChild()来获取文本节点是多余的