Android: Sax parsing returns null values and retrieve values in tags of same name

我只是一个虾纸丫 提交于 2019-11-28 11:48:22

This code makes the incorrect assumption that the characters method will be called only once between the startElement and endElement calls for a tag.

Instead of having the logic for setting the values in the characters method, you need initialize a buffer in the startElement method, collect characters into the buffer in the characters method, and then make the assignments and clear the buffer in the endElement method.

EDIT:

Actually, there were a few other issues in your code...

You had setMobilePhone and setWorkPhone in your model class setting the homePhone field... An inevitable risk when you copy-modify code.

And your handler was only creating one result, and would have overwritten and only returned the last one in the file.

I've played with it, changed some of the methods more to Java standard naming, and changed some of the xml to CamelCase as well.

Revised XML:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<PhoneBook>
    <PhoneBookEntry>
        <FirstName>John</FirstName>
        <LastName>Connor</LastName>
        <Address>5,Downing Street</Address>
        <Phone loc="home">9875674567</Phone>
        <Phone loc="work">9875674567</Phone>
        <Phone loc="mobile">78654562341</Phone>
    </PhoneBookEntry>
    <PhoneBookEntry>
        <FirstName>John</FirstName>
        <LastName>Smith</LastName>
        <Address>6,Downing Street</Address>
        <Phone loc="home">678-56-home</Phone>
        <Phone loc="work">678-59-work</Phone>
        <Phone loc="mobile">678-85-mobile</Phone>
    </PhoneBookEntry>
</PhoneBook>

Revised ParsedExampleDataSet:

public class ParsedExampleDataSet {
    private String firstName = null;
    private String lastName =null;
    private String address =null;
    private String homePhone =null;
    private String workPhone =null;
    private String mobilePhone =null;


    //Firstname
    public String getFirstName() {
         return firstName;
    }
    public void setFirstName(String firstName) {
         this.firstName = firstName;
    }

    //Lastname
    public String getLastName(){
        return lastName;
    }
    public void setLastName(String lastName){
        this.lastName = lastName;
    }

    //address
    public String getAddress(){
        return address;
    }
    public void setAddress(String Address){
        this.address =Address;
    }

    public void setHomePhone(String homePhone){
        this.homePhone =homePhone;
    }
    public void setWorkPhone(String homePhone){
        this.workPhone =homePhone;
    }
    public void setMobilePhone(String homePhone){
        this.mobilePhone =homePhone;
    }


    public String toString(){
         return "firstName: " + this.firstName + "\n" + "lastName=: " + this.lastName + "\n" + "address: " + this.address + "\n"  + "homePhone: " + this.homePhone + "\n" + "workPhone: " + this.workPhone + "\n" + "mobilePhone: " + this.mobilePhone;

    }
}

And the handler that does the parsing:

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

import java.util.ArrayList;
import java.util.List;

public class ExampleHandler extends DefaultHandler {

    // ===========================================================
    // Fields
    // ===========================================================

    private boolean in_homePhone = false;
    private boolean in_workPhone = false;
    private boolean in_mobilePhone = false;

    private StringBuffer stringBuffer;

    private List<ParsedExampleDataSet> myParsedExampleDataSets;
    private ParsedExampleDataSet myParsedExampleDataSet;

    // ===========================================================
    // Methods
    // ===========================================================

    public List<ParsedExampleDataSet> getParsedData() {
        return myParsedExampleDataSets;
    }

    @Override
    public void startDocument() throws SAXException {
        myParsedExampleDataSets = new ArrayList<ParsedExampleDataSet>();
        stringBuffer = new StringBuffer();
    }

    @Override
    public void endDocument() throws SAXException {
        // Nothing to do
    }

    /**
     * Gets be called on opening tags like:
     * <tag>
     * Can provide attribute(s), when xml was like:
     * <tag attribute="attributeValue">
     */
    @Override
    public void startElement(String namespaceURI, String localName,
                             String qName, Attributes atts) throws SAXException {

        if (qName.equals("PhoneBookEntry")) {
            myParsedExampleDataSet = new ParsedExampleDataSet();
        }

        if (qName.equals("Phone")) {
            String phoneLocation = atts.getValue("loc");
            if (phoneLocation.equals("home")) {
                this.in_homePhone = true;
            } else if (phoneLocation.equals("work")) {
                this.in_workPhone = true;
            } else if (phoneLocation.equals("mobile")) {
                this.in_mobilePhone = true;
            }
        }
    }

    /**
     * Gets be called on closing tags like:
     * </tag>
     */
    @Override
    public void endElement(String namespaceURI, String localName, String qName)
            throws SAXException {

        String result = stringBuffer.toString();
        stringBuffer.setLength(0);

        if (in_homePhone) {
            myParsedExampleDataSet.setHomePhone(result);
            in_homePhone = false;
        }
        else if (in_mobilePhone) {
            myParsedExampleDataSet.setMobilePhone(result);
            in_mobilePhone = false;
        }
        else if (in_workPhone) {
            myParsedExampleDataSet.setWorkPhone(result);
            in_workPhone = false;
        }
        else if (qName.equals("FirstName")) {
            myParsedExampleDataSet.setFirstName(result);
        }
        else if (qName.equals("LastName")) {
            myParsedExampleDataSet.setLastName(result);
        }
        else if (qName.equals("Address")) {
            myParsedExampleDataSet.setAddress(result);
        }
        else if (qName.equals("PhoneBookEntry")) {
            myParsedExampleDataSets.add(myParsedExampleDataSet);
        }
    }

    /**
     * Gets be called on the following structure:
     * <tag>characters</tag>
     */
    @Override
    public void characters(char ch[], int start, int length) {
        stringBuffer.append(new String(ch, start, length));
    }

}

It puts some likely unwanted whitespace in the fields, but I suspect you can figure out how to trim that.

Calling it, you get a list rather than a single object, but other than dealing with that, your calling code shouldn't have to change too much. I didn't try to work with that, as I'm not doing any of this on android.

Also to get the attributes from an element you can use something like this: You get the attributes from the atts Attributes in the startElement method.

}else if (localName.equals("Phone")){
          this.in_Phone=true;
          int length = atts.getLength();
          System.out.println("length = " + length);
          for(int i = 0; i < length; i++){
              String name = atts.getQName(i);
              System.out.println(name);
              String value = atts.getValue(i);
              System.out.println(value);
              if(name.equals("loc")){
                  if(value.equals("home")){
                    this.in_homePhone=true;
                  }else if(value.equals("work")){
                    this.in_workPhone=true;
                  }else if(value.equals("mobile")){
                    this.in_mobilePhone=true;
                 }

              }
          }
    }
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!