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

前端 未结 2 403

I have these XML on a URL

 

    
        John&         


        
相关标签:
2条回答
  • 2020-12-11 00:03

    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.

    0 讨论(0)
  • 2020-12-11 00:05

    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;
                     }
    
                  }
              }
        }
    
    0 讨论(0)
提交回复
热议问题