简体   繁体   English

SAX Parser - 如何处理来自.XML文件的错误数据

[英]SAX Parser - How To Handle Bad Data From .XML File

I need to make a program that takes an .xml file that uses the SAX Parser in Java to parse the .xml file, store it in an arrayList and then call methods to display certain objects with the arrayList. 我需要创建一个程序,该程序采用.xml文件,该文件使用Java中的SAX Parser来解析.xml文件,将其存储在arrayList中,然后调用方法以使用arrayList显示某些对象。

My program needs to be able to handle the user giving the SAX Parser bad data such that if it doesn't have a certain tag it's looking for, then it won't break. 我的程序需要能够处理给SAX Parser坏数据的用户,这样如果它没有它正在寻找的某个标签,那么它就不会中断。 I need it to be able to load the data and use a “check” command to check the intergrity of the data. 我需要它能够加载数据并使用“检查”命令来检查数据的完整性。 For example, if the customer doest't have an account associated with it, the program will output which customer doesn't have an account. 例如,如果客户没有与之关联的帐户,则程序将输出哪个客户没有帐户。

Below, I've put the task for the program, the Handler, and the .xml with bad data below. 下面,我将程序,Handler和.xml的任务放在下面的错误数据中。

Task for the program: 该计划的任务:

check : This command is used to check the integrity of the named entries. check:此命令用于检查命名条目的完整性。 In other words, it checks to see that all the entries of a given type are correct. 换句话说,它检查给定类型的所有条目是否正确。 For example, if the command is: check customer the program should list all customers (first name and last name) that do not have any accounts. 例如,如果命令是:检查客户,程序应列出没有任何帐户的所有客户(名字和姓氏)。 Related commands include: check account : list any account number without an associated address check address : list any address without an associated meter check meter : list any meter id without any meter readings, or whose readings do not match the meter type, eg, push reading from a polling meter. 相关命令包括:​​支票帐户:列出没有相关地址检查地址的任何帐号:列出没有相关仪表检查仪表的任何地址:列出没有任何仪表读数的任何仪表ID,或者其读数与仪表类型不匹配,例如推送从投票仪上读。

.xml File: .xml文件:

 <xml version="1.0" encoding="UTF-8">
    <!-- Customer with no account -->
    <customer lastName ="Anderson" firstName="Thomas">

    </customer>

    <!-- Account with no address -->    
    <customer lastName ="Baker" firstName="Susanne">
        <account type="residential" accountNumber="999-999-99">              
        </account>
    </customer>

    <!-- Address with no meter -->    
    <customer lastName ="Charles" firstName="Henry">
        <account type="residential" accountNumber="888-888-88">   
            <address type="apartment" unit="308" street="E 6th St." number="56" zipCode="13126"/>           
        </account>
    </customer>

    <!-- Meter with no readings -->    
    <customer lastName ="Davidson" firstName="Mary">
        <account type="residential" accountNumber="666-666-66">   
            <address type="apartment" unit="308" street="W 9th St." number="67" zipCode="13126">
                <meter id = "RM-4876-X4" brand="GE" type="poll" location = "West side of building"/>
            </address>           
        </account>
    </customer>

    <!-- Meter with mismatched readings -->    
    <customer lastName ="Evans" firstName="Oscar">
        <account type="residential" accountNumber="555-555-55">   
            <address type="house" street="E 10th St." number="78" zipCode="13126">
                <meter id = "RM-4874-X4" brand="GE" type="poll" location = "North side">
                    <meterReading reading="650" date = "1413227815" flag="poll"/>
                    <meterReading reading="675" date = "1413314215" flag="push"/>
                    <meterReading reading="622" date = "1413400615" flag="poll"/>
                </meter>
            </address>           
        </account>
    </customer>
</xml>

Handler File: 处理程序文件:

    package csc241hw07;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class MyHandler extends DefaultHandler {

    // Variables to hold current values
    private ArrayList<Customer> customerList = new ArrayList<Customer>();
    private Customer currentCustomer;
    private Account currentAccount;
    private Address currentAddress;
    private Meter currentMeter;

    //getter method for employee list
    public ArrayList<Customer> getCustList() {
        return customerList;
    }

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes)
            throws SAXException {

        if (qName.equalsIgnoreCase("customer")) {
            //Create a customer object
            String lastName = attributes.getValue("lastName");
            String firstName = attributes.getValue("firstName");
            currentCustomer = new Customer(lastName, firstName);

        } else if (qName.equalsIgnoreCase("address")) {
            // Create an Address object
            String street = attributes.getValue("street");
            int houseNumber = Integer.parseInt(attributes.getValue("number"));
            String zipCode = attributes.getValue("zipCode");
            String type = attributes.getValue("type");
            String unit = attributes.getValue("unit");

            if (type.equalsIgnoreCase("mailing")) {
                // this is a mailing address -- assign to current customer
                MailingAddress ma = new MailingAddress(street, houseNumber, zipCode, type);
                currentCustomer.setMailingAddress(ma);
            } else if (type.equalsIgnoreCase("house")) {
                // Create a house
                currentAddress = new House(street, houseNumber, zipCode, type);
            } else if (type.equalsIgnoreCase("commercial")) {
                // Create a commercial
                currentAddress = new Commercial(street, houseNumber, zipCode, type);
            } else if (unit != null) {
                // Create an apartment
                currentAddress = new Apartment(street, houseNumber, zipCode, type, unit);
            } else {
                System.out.println("Unknown address type:" + type);
            }


            if (currentAddress != null) {
                // Assign this account to current address
                currentAddress.setAccount(currentAccount);
                currentAccount.addAddress(currentAddress);
            }

        } else if (qName.equalsIgnoreCase("meter")) {
            // Create a meter object
            String type = attributes.getValue("type");
            String brand = attributes.getValue("brand");
            String id = attributes.getValue("id");
            if (type.equalsIgnoreCase("push")) {
                currentMeter = new PushMeter(id, brand, type);
            } else if (type.equalsIgnoreCase("poll")) {
                currentMeter = new PollMeter(id, brand, type);
            } else {
                System.out.println("Unknown meter type: " + type);
            }


            if (currentMeter != null) {
                // Set location
                String location = attributes.getValue("location");
                currentMeter.setLocation(currentAddress, location);
                currentAddress.addMeter(currentMeter);
            }

            //System.out.println("METER:");
        } else if (qName.equalsIgnoreCase("meterReading")) {
            // Create a meter reading
            //<meterReading reading="622" date = "1413400615" flag="push"/>
            double reading = Double.parseDouble(attributes.getValue("reading"));
            //System.out.println("DATE:" );
            ZoneOffset z = ZoneOffset.ofHours(5);
            long epoch = Long.parseLong(attributes.getValue("date"));
            LocalDateTime d = LocalDateTime.ofEpochSecond(epoch,0,z);
            //System.out.println("DATE:" + d.toString());
            String flag = attributes.getValue("flag");
            MeterReading mr = new MeterReading(reading, d, flag, currentMeter);
            // Add this to current meter
            currentMeter.addReading(mr);
            //System.out.println("METERREADING:");

        } else if (qName.equalsIgnoreCase("account")) {
//    <account type="residential" accountNumber="876-543-21">
            String type = attributes.getValue("type");
            String acctNum = attributes.getValue("accountNumber");
            if (type.equalsIgnoreCase("residential")) {
                // residential account
                currentAccount = new ResidentialAccount(acctNum, currentCustomer);
            } else if (type.equalsIgnoreCase("commercial")) {
                currentAccount = new CommercialAccount(acctNum, currentCustomer);
            } else {
                System.out.println("Unknown account type:" + type);
            }

            if (currentAccount != null) {
                // Add this account to current customer
                currentCustomer.addAccount(currentAccount);
            }
        }
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        if (qName.equalsIgnoreCase("customer")) {
            customerList.add(currentCustomer);
            currentCustomer = null;
        } else if (qName.equalsIgnoreCase("meter")) {
            currentMeter = null;
        } else if (qName.equalsIgnoreCase("account")) {
            currentAccount = null;
        } else if (qName.equalsIgnoreCase("address")) {
            currentAddress = null;
        }
    }
}

Thank you! 谢谢!

You can add one more list with "bad" customers like: 您可以添加一个“坏”客户列表,例如:

// Variables to hold current values
private ArrayList<Customer> customerList = new ArrayList<Customer>();
private ArrayList<Customer> badCustomerList = new ArrayList<Customer>();
...

And add some changes sorting those customers out of "good" ones. 并添加一些更改,将这些客户排除在“好”客户之外。 For instance: 例如:

@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
    if (qName.equalsIgnoreCase("customer")) {
        if (isCustomerGood(currentCustomer)) {      // Here is checking code
            customerList.add(currentCustomer);
        } else {
            badCustomerList.add(currentCustomer);
        }
        currentCustomer = null;
    } else if (qName.equalsIgnoreCase("meter")) {
        currentMeter = null;
    } else if (qName.equalsIgnoreCase("account")) {
        currentAccount = null;
    } else if (qName.equalsIgnoreCase("address")) {
        currentAddress = null;
    }
}

private static boolean isCustomerGood(Customer customer) {
    return customer.getAccount() != null;
}

public boolean check() {
    return badCustomerList.isEmpty();
}

public List<Customer> getBadCustomers() {
    return badCustomerList;
}

Actually you can implement isCustomerGood differently depending on your needs. 实际上,您可以根据需要以不同方式实现isCustomerGood Now you just run check method at the end of parsing. 现在,您只需在解析结束时运行check方法。

First of all, by bad data I dont think you mean a non-wellformed XML file that causes parsing exception. 首先,糟糕的数据我不认为你的意思是一个非正常的XML文件导致解析异常。

If the above assumption is true, then I think you should consider using XPath to query the data file and check for the condition where the target element does not exist... 如果上述假设为真,那么我认为你应该考虑使用XPath来查询数据文件并检查目标元素不存在的条件......

So why are you not using XPath which would make your code a lot easier to write and maintain? 那你为什么不使用XPath来使你的代码更容易编写和维护呢?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM