如何使用Stax从xml文件中提取属性值?

时间:2014-01-29 12:14:10

标签: java xml xml-parsing stax

我必须使用stax解析xml文件,除了一点之外,我主要完成了我需要的工作。

我的代码逻辑不会在右侧提取属性。接下来是我的输出:

Employee { name=Carl Cracker, salary=75000.0, hireDay=null }
Employee { name=Harry Hacker, salary=50000.0, hireDay=null }
Employee { name=Tony Tester, salary=40000.0, hireDay=null }

以下是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 StaxXmlParser {    
    private List<Employee> employeeList;
    private Employee currentEmployee;
    private String tagContent;
    private XMLStreamReader reader;

    public StaxXmlParser(String filename) {
        employeeList = null;
        currentEmployee = null;
        tagContent = null;

        try {
            XMLInputFactory factory = XMLInputFactory.newFactory();
            reader = factory.createXMLStreamReader(new FileInputStream(new File(filename)));
            parseEmployee();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public List<Employee> parseEmployee() throws XMLStreamException {
        while (reader.hasNext()) {
            int event = reader.next();

            switch (event) {
                case XMLStreamConstants.START_ELEMENT:
                    if ("employee".equals(reader.getLocalName())) {
                        currentEmployee = new Employee();
                    }
                    if ("staff".equals(reader.getLocalName())) {
                        employeeList = new ArrayList<>();
                    }
                    if ("hireday".equals(reader.getLocalName())) {
                        int yearAttr = Integer.parseInt(reader.getAttributeValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "year"));
                        int monthAttr = Integer.parseInt(reader.getAttributeValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "month"));
                        int dayAttr = Integer.parseInt(reader.getAttributeValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "day"));

                        currentEmployee.setHireDay(yearAttr, monthAttr, dayAttr);
                    }
                    break;

                case XMLStreamConstants.CHARACTERS:
                    tagContent = reader.getText().trim();
                    break;

                case XMLStreamConstants.END_ELEMENT:
                    switch (reader.getLocalName()) {
                        case "employee":
                            employeeList.add(currentEmployee);
                            break;
                        case "name":
                            currentEmployee.setName(tagContent);
                            break;
                        case "salary":
                            currentEmployee.setSalary(Double.parseDouble(tagContent));
                            break;
                    }
            }
        }    
        return employeeList;
    }    
}

这里是Employee class:

的内容
class Employee {

    private String name;
    private double salary;
    private Date hireDay;

    public Employee() {}

    public Employee(String n, double s, int year, int month, int day) {
        name = n;
        salary = s;
        GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
        // GregorianCalendar uses 0 for January
        hireDay = calendar.getTime();
    }

    public String getName() {
        return name;
    }

    public double getSalary() {
        return salary;
    }

    public Date getHireDay() {
        return hireDay;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public void setHireDay(Date hireDay) {
        this.hireDay = hireDay;
    }

    public void setHireDay(int year, int month, int day) {
        GregorianCalendar calendar = new GregorianCalendar(year, month, day);
        this.hireDay = calendar.getTime();
    }

    public void raiseSalary(double byPercent) {
        double raise = salary * byPercent / 100;
        salary += raise;
    }

    @Override
    public String toString() {
        return String.format("Employee { name=%s, salary=%s, hireDay=%s }", name, salary, hireDay);
    }

    @Override
    public int hashCode() {
        return super.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        return super.equals(obj);
    }
}

如何通过stax提取属性?

1 个答案:

答案 0 :(得分:3)

我在这里看到了3个问题:

  1. 您正在从XML检索hireday而不是hiredate标记;应该是:if ("hiredate".equals(reader.getLocalName()))

  2. 您正在使用XML所没有的命名空间检索各个属性。将其更改为NULL,例如:

    int yearAttr = Integer.parseInt(reader.getAttributeValue(null, "year"));

  3. Java中的日历类考虑从0开始的月份(0表示1月份)。因此,您的价值12将继续下一年。您可能希望从月份值中减去1以获得所需的输出。

    currentEmployee.setHireDay(yearAttr, monthAttr - 1, dayAttr);

  4. 您修改后的parseEmployee()

    public List<Employee> parseEmployee() throws XMLStreamException {
            while (reader.hasNext()) {
                int event = reader.next();
    
                switch (event) {
                case XMLStreamConstants.START_ELEMENT:
                    if ("employee".equals(reader.getLocalName())) {
                        currentEmployee = new Employee();
                    }
                    if ("staff".equals(reader.getLocalName())) {
                        employeeList = new ArrayList<>();
                    }
                    if ("hiredate".equals(reader.getLocalName())) {
                        int yearAttr = Integer.parseInt(reader.getAttributeValue(
                                null, "year"));
                        int monthAttr = Integer.parseInt(reader.getAttributeValue(
                                null, "month"));
                        int dayAttr = Integer.parseInt(reader.getAttributeValue(
                                null, "day"));
    
                        currentEmployee
                                .setHireDay(yearAttr, monthAttr - 1, dayAttr);
                    }
                    break;
    
                case XMLStreamConstants.CHARACTERS:
                    tagContent = reader.getText().trim();
                    break;
    
                case XMLStreamConstants.END_ELEMENT:
                    switch (reader.getLocalName()) {
                    case "employee":
                        employeeList.add(currentEmployee);
                        break;
                    case "name":
                        currentEmployee.setName(tagContent);
                        break;
                    case "salary":
                        currentEmployee.setSalary(Double.parseDouble(tagContent));
                        break;
                    }
                }
            }
            return employeeList;
        }
    

    现在你得到了正确的输出:

    Employee { name=Carl Cracker, salary=75000.0, hireDay=Tue Dec 15 00:00:00 IST 1987 }
    Employee { name=Harry Hacker, salary=50000.0, hireDay=Sun Oct 01 00:00:00 IST 1989 }
    Employee { name=Tony Tester, salary=40000.0, hireDay=Thu Mar 15 00:00:00 IST 1990 }