2016-04-07 4 views
1

Ich brauche ein Programm, das eine XML-Datei verwendet, die den SAX-Parser in Java verwendet, um die .xml-Datei zu analysieren, in einer ArrayList zu speichern und Methoden aufzurufen um bestimmte Objekte mit der ArrayListe anzuzeigen.SAX-Parser - Umgang mit fehlerhaften Daten aus .XML-Datei

Mein Programm muss in der Lage sein, mit dem Benutzer umzugehen, der dem SAX-Parser schlechte Daten gibt, so dass, wenn er nicht nach einem bestimmten Tag sucht, er nicht bricht. Ich brauche es, um die Daten laden zu können und einen "check" -Befehl zu verwenden, um die Integrität der Daten zu überprüfen. Wenn dem Kunden beispielsweise kein Konto zugeordnet ist, gibt das Programm aus, welcher Kunde kein Konto hat.

Im Folgenden habe ich die Aufgabe für das Programm, den Handler und die .xml mit schlechten Daten unten aufgeführt.

Aufgabe für das Programm:

Prüfung: Mit diesem Befehl wird die Integrität der genannten Einträge zu überprüfen. Mit anderen Worten, es überprüft, ob alle Einträge eines bestimmten Typs korrekt sind. Wenn der Befehl beispielsweise lautet: Überprüfen Sie den Kunden , das Programm sollte alle Kunden (Vorname und Nachname) auflisten, die keine Konten haben. Verwandte Befehle sind: Konto überprüfen: jede Kontonummer ohne eine zugehörige Adresse auflisten Adresse überprüfen: eine beliebige Adresse ohne zugehöriges Messgerät auflisten Zähler prüfen: eine Zähler-ID ohne Zählerstände auflisten oder deren Messwerte nicht mit dem Zählertyp übereinstimmen, zB Push-Lesen von einem Polling-Meter.

.xml Datei:

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

+1

Haben Sie sich JaxB angesehen? Es behandelt elegant fehlende Tags. Es wird nicht mit fehlerhaften XML umgehen, aber ich glaube nicht, dass Sie das suchen. Keine Notwendigkeit, dies alles von Hand zu schreiben. –

+2

Und was ist die Frage zu beantworten? – rpy

+0

Die Frage, die ich stelle, lautet: Wenn der Parser nach einem bestimmten Tag sucht und es nicht finden kann, wie zeige ich dem Benutzer an, dass die von ihm verwendete .xml-Datei kein Tag enthält? – LJP1203

Antwort

0

Sie können mit „schlechten“ Kunden wie eine weitere Liste:

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

Und einige Änderungen hinzufügen, die Kunden aus „gut“ diejenigen zu sortieren. Zum Beispiel:

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

Eigentlich kann man isCustomerGood unterschiedlich je nach Bedarf implementieren. Jetzt starten Sie einfach check Methode am Ende der Analyse.

0

Zunächst einmal, durch schlechte Daten glaube ich nicht, dass Sie eine nicht-wohlgeformte XML-Datei, die Parsing-Ausnahme verursacht.

Wenn die obige Annahme wahr ist, dann denke ich, sollten Sie mit XPath betrachten die Datendatei abzufragen und für den Zustand prüfen, wo das Zielelement nicht existiert ...

Warum sind Sie nicht mit XPath Was würde Ihren Code viel einfacher zu schreiben und zu pflegen machen?