安卓:SAX解析返回空值,并在同一个名称标签检索值并在、名称、标签、SAX

2023-09-13 01:21:56 作者:你瞎发什么光i

我有这些XML一个网址

I have these XML on a URL

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

我能够提取的名字,姓氏和地址的值,但是当涉及到​​手机的标签,我的code返回空值。这里是我的code:

I was able to extract the values on firstname, lastname and Address, but when it comes to Phone tags, my code returns null values. Here are my code:

ParsingXML.java

package com.example.parsingxml;

import java.net.Proxy;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.URL;
import java.net.URLConnection;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class ParsingXML extends Activity {



    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
         //System.setProperty("http.proxyHost"," 129.188.69.100 "); 
         //System.setProperty("http.proxyPort","1080");
         //System.setProperty("http.nonProxyHosts","10.228.97.76");

         /* Create a new TextView to display the parsingresult later. */
         TextView tv = new TextView(this);
         try {
              /* Create a URL we want to load some xml-data from. */
              URL url = new URL("http://somedomain.com/jm/sampleXML.xml");
                           URLConnection ucon = url.openConnection();
              /* Get a SAXParser from the SAXPArserFactory. */
              SAXParserFactory spf = SAXParserFactory.newInstance();
              SAXParser sp = spf.newSAXParser();

              /* Get the XMLReader of the SAXParser we created. */
              XMLReader xr = sp.getXMLReader();
              /* Create a new ContentHandler and apply it to the XML-Reader*/
              ExampleHandler myExampleHandler = new ExampleHandler();
              xr.setContentHandler(myExampleHandler);

              /* Parse the xml-data from our URL. */
              xr.parse(new InputSource(url.openStream()));
              /* Parsing has finished. */

              /* Our ExampleHandler now provides the parsed data to us. */
              ParsedExampleDataSet parsedExampleDataSet =
                                            myExampleHandler.getParsedData();

              /* Set the result to be displayed in our GUI. */
              tv.setText(parsedExampleDataSet.toString());

         } catch (Exception e) {
              /* Display any Error to the GUI. */
              tv.setText("Error: " + e.getMessage());

         }
         /* Display the TextView. */
         this.setContentView(tv);
    }
}

ExampleHandler.java

package com.example.parsingxml;

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


public class ExampleHandler extends DefaultHandler{

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

     private boolean in_outertag = false;
     private boolean in_innertag = false;
     private boolean in_firstname = false;
     private boolean in_lastname= false;
     private boolean in_Address=false;
     private boolean in_Phone=false;
     private boolean in_homePhone=false;
     private boolean in_workPhone=false;
     private boolean in_mobilePhone=false;


     private ParsedExampleDataSet myParsedExampleDataSet = new ParsedExampleDataSet();

     // ===========================================================
     // Getter & Setter
     // ===========================================================

     public ParsedExampleDataSet getParsedData() {
          return this.myParsedExampleDataSet;
     }

     // ===========================================================
     // Methods
     // ===========================================================
     @Override
     public void startDocument() throws SAXException {
          this.myParsedExampleDataSet = new ParsedExampleDataSet();
     }

     @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 (localName.equals("PhoneBook")) {
               this.in_outertag = true;
          }else if (localName.equals("PhonebookEntry")) {
               this.in_innertag = true;
          }else if (localName.equals("firstname")) {
               this.in_firstname = true;
          }else if (localName.equals("lastname"))  {
              this.in_lastname= true;
          }else if(localName.equals("Address"))  {
              this.in_Address= true;
          }else if (localName.equals("Phone")){
              this.in_Phone=true;
              String phoneattr=atts.getValue("loc");
              if(phoneattr.equals("home")){
                this.in_homePhone=true;
              }else if(phoneattr.equals("work")){
                this.in_workPhone=true;
              }else if(phoneattr.equals("mobile")){
                this.in_mobilePhone=true;
             }
        }  


          }

              //else if (localName.equals("tagwithnumber")) {
         // }
               // Extract an Attribute
              // String attrValue = atts.getValue("thenumber");
              // int i = Integer.parseInt(attrValue);
              // myParsedExampleDataSet.setExtractedInt(i);
        //  }


     /** Gets be called on closing tags like:
      * </tag> */
     @Override
     public void endElement(String namespaceURI, String localName, String qName)
               throws SAXException {
          if (localName.equals("Phonebook")) {
               this.in_outertag = false;
          }else if (localName.equals("PhonebookEntry")) {
               this.in_innertag = false;
          }else if (localName.equals("firstname")) {
               this.in_firstname = false;
          }else if (localName.equals("lastname"))  {
              this.in_lastname= false;
          }else if(localName.equals("Address"))  {
              this.in_Address= false;
          }else if(localName.equals("Phone"))   {
              this.in_Phone=false;
          }
     }

     /** Gets be called on the following structure:
      * <tag>characters</tag> */
     @Override
    public void characters(char ch[], int start, int length) {
          if(this.in_firstname){
          myParsedExampleDataSet.setfirstname(new String(ch, start, length));
          }
          if(this.in_lastname){
          myParsedExampleDataSet.setlastname(new String(ch, start, length));
          }
          if(this.in_Address){
              myParsedExampleDataSet.setAddress(new String(ch, start, length));
          }
          if(this.in_homePhone){
              myParsedExampleDataSet.sethomePhone(new String(ch, start, length));
          }
          if(this.in_workPhone){
              myParsedExampleDataSet.setworkPhone(new String(ch, start, length));
          }
          if(this.in_mobilePhone){
              myParsedExampleDataSet.setmobilePhone(new String(ch, start, length));
          }
    }
}

ParsedExampleDataSet.java

package com.example.parsingxml;

public class ParsedExampleDataSet {
    private String firstname = null;
    private String lastname=null;
    private String Address=null;
    private String Phone=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;
    }

    //Phone
    public String getPhone(){
        return Phone;
    }
    public void sethomePhone(String homePhone){
        this.homephone=homePhone;
    }
    public void setworkPhone(String homePhone){
        this.homephone=homePhone;
    }
    public void setmobilePhone(String homePhone){
        this.homephone=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;

    }
}

另一件事,我怎么能在PhonebookEntry标签检索这两个值?

Another thing how can I retrieve both values in PhonebookEntry tags?

我有点新的Java和Android开发人员,许多在此先感谢! :)

I'm kinda new to java and android dev, many thanks in advance! :)

推荐答案

这code,使不正确的假设,即字符方法将被调用一次的的startElement 的endElement 要求的标签。

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

而不是有逻辑在人物设定值方法,你需要初始化一个缓冲区,在的startElement 方法,收集字符转换成在字符缓冲区的方法,然后进行分配并清空缓冲区中的的endElement 方法。

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.

编辑:

其实,有你的code其他一些问题...

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

您已经setMobilePhone和setWorkPhone在你的模型类设置HOMEPHONE场...当你复制,修改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.

我打它,改变了一些方法更到Java标准命名,并改变了一些XML来驼峰为好。

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.

修改后的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>

修订ParsedExampleDataSet:

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;

    }
}

和,做解析处理程序:

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.

调用它,你就会得到一个列表,而不是一个单一的对象,但比处理其他,您的电话code应该不会有太大变动。我没有尝试与工作,因为我没有做任何这在Android上。

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.