Android:Sax解析返回空值并检索同名标记中的值

Android:Sax解析返回空值并检索同名标记中的值,android,xml,sax,Android,Xml,Sax,我在URL上有这些XML <?xml version="1.0" encoding="ISO-8859-1" ?> <Phonebook> <PhonebookEntry> <firstname>John</firstname> <lastname>Connor</lastname> <Address>5,Downing Street<

我在URL上有这些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>
ExampleHandler.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);
    }
}
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));
          }
    }
}
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标记中检索这两个值


我是java和android开发的新手,非常感谢!)

此代码错误地假设在
startElement
endElement
调用标记之间只调用一次
characters
方法

您不需要在
characters
方法中设置值的逻辑,而需要在
startElement
方法中初始化缓冲区,在
characters
方法中将字符收集到缓冲区中,然后在
endElement
方法中进行赋值并清除缓冲区

编辑:

实际上,代码中还有一些其他问题

您在模型类中设置了setMobilePhone和setWorkPhone,设置了homePhone字段。。。复制或修改代码时不可避免的风险

您的处理程序只创建了一个结果,并且将覆盖并仅返回文件中的最后一个结果

我已经使用了它,将一些方法更多地更改为Java标准命名,并将一些xml更改为CamelCase

修订的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>
以及执行解析的处理程序:

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

}
import org.xml.sax.Attributes;
导入org.xml.sax.SAXException;
导入org.xml.sax.helpers.DefaultHandler;
导入java.util.ArrayList;
导入java.util.List;
公共类ExampleHandler扩展了DefaultHandler{
// ===========================================================
//田地
// ===========================================================
_homePhone中的私有布尔值=false;
_workPhone中的私有布尔值=false;
_mobilePhone中的私有布尔值=false;
私有字符串缓冲区字符串缓冲区;
私有列表MyParsedExampledataset;
私有ParsedExampleDataSet myParsedExampleDataSet;
// ===========================================================
//方法
// ===========================================================
公共列表getParsedData(){
返回myParsedExampleDataSets;
}
@凌驾
public void startDocument()引发异常{
myParsedExampleDataSets=new ArrayList();
stringBuffer=新的stringBuffer();
}
@凌驾
public void endDocument()引发异常{
//无事可做
}
/**
*在开始标记上调用的获取,如:
* 
*当xml类似于以下内容时,可以提供属性:
* 
*/
@凌驾
public void startElement(字符串namespaceURI、字符串localName、,
字符串qName、属性atts)引发异常{
if(qName.equals(“PhoneBookEntry”)){
myParsedExampleDataSet=新的ParsedExampleDataSet();
}
如果(qName.equals(“电话”)){
字符串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;
}
}
}
/**
*在关闭标记上调用的控件,如:
* 
*/
@凌驾
public void endElement(字符串namespaceURI、字符串localName、字符串qName)
抛出SAX异常{
字符串结果=stringBuffer.toString();
stringBuffer.setLength(0);
如果(在家庭电话中){
myParsedExampleDataSet.setHomePhone(结果);
in_homePhone=false;
}
否则,如果(在移动电话中){
myParsedExampleDataSet.setMobilePhone(结果);
in_mobilePhone=假;
}
else if(在工作电话中){
myParsedExampleDataSet.setWorkPhone(结果);
in_workPhone=假;
}
else if(qName.equals(“FirstName”)){
myParsedExampleDataSet.setFirstName(结果);
}
else if(qName.equals(“LastName”)){
myParsedExampleDataSet.setLastName(结果);
}
else if(qName.equals(“地址”)){
myParsedExampleDataSet.setAddress(结果);
}
else if(qName.equals(“PhoneBookEntry”)){
添加(myParsedExampleDataSet);
}
}
/**
*无法在以下结构上调用的获取:
*人物
*/
@凌驾
公共无效字符(字符ch[],整数开始,整数长度){
append(新字符串(ch,start,length));
}
}
它在字段中放置了一些可能不需要的空格,但我怀疑您可以找到如何修剪这些空格的方法


调用它,您将得到一个列表,而不是一个对象,但是除了处理它之外,您的调用代码不必做太多更改。我没有尝试使用它,因为我没有在android上执行任何操作。

这段代码错误地假设
characters
方法在
startElement
endElement
调用标记之间只调用一次

您不需要在
characters
方法中设置值的逻辑,而需要在
startElement
方法中初始化缓冲区,在
characters
方法中将字符收集到缓冲区中,然后在
endElement
方法中进行赋值并清除缓冲区

编辑:

实际上,代码中还有一些其他问题

您在模型类中设置了setMobilePhone和setWorkPhone,设置了homePhone字段。。。复制或修改代码时不可避免的风险

您的处理程序只创建了一个结果,并且将覆盖并仅返回文件中的最后一个结果

我玩过,改变了一些
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));
    }

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

              }
          }
    }