Android 个人学习笔记之---SAX解析XML文件(有一个坑爹的问题)

博主分享学习XML解析的经历,重点介绍SAX解析方法。提到继承ContentHandler类开发不便,可继承DefaultHandler类。还说明了android中使用SAX解析xml文件的步骤,最后博主遇到调用方法出错问题,希望得到解答。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

               

今天晚上我学习了下XML的解析,解析XML方法有SAX和DOM解析和Pull解析,今天先学习了下SAX,每天8点下班,下班回来还要自己做饭,所以每天我都要奋斗到1点左右,然后早上8点起来做饭带到公司去吃,刚毕业的程序猿很苦逼吧,不过不要紧,我相信通过我的努力,这一切都会改变,fighting...哈哈,废话不多说了,看项目吧

如果要用SAX来解析xml文档,则需要一个类来继承android系统提供的ContentHandler类。但是如果继承ContentHandler这个类, 即使你不使用这个类提供的所有方法,你也必须实现其内部的所有方法(一般情况下没有使用的方法可以直接用空方法代替),但是这样开发起来不是很方便。因此我们可以改为继承DefaultHandler这个类,这样的话我们只需要实现程序中所需要的方法即可,其它的方法这个类内部其实已经用空方法代替了。

ContentHandler接口的方法有以下几种:void startDocument();//文档解析开始时执行void endDocument();//文档解析结束时执行void startElement(String uri, String localName, String qName, Attributes atts);//标签开始解析时执行void endElement(String uri, String localName, String qName, Attributes atts);//标签解析结束时执行void characters(char[] ch, int start, int length );//解析标签属性时执行

android中使用SAX来解析xml文件,需先建立一个SAX工厂,即SAXParserFactory对象,还需建立一个XMLReader对象,该类绑定ContentHandler子类,且与xml源文件结合在一起。即其处理过程为创建事件处理程序,创建SAX解析器,键事件处理程序分配给解析器,对文档进行解析,将每个事件发送给处理程序。

1.在src目录下新建一个android.xml文件

<?xml version="1.0" encoding="UTF-8"?><persons>    <person id="23">        <name>xiaanming</name>        <age>23</age>    </person>    <person id="20">        <name>liudehua</name>        <age>28</age>    </person></persons>

2.新建一个Person.class用来存放解析的对象

package com.example.xml_parser;public class Person private int id; private String name; private int age;  public Person(){}  public Person(int id, String name, int age){  this.id = id;  this.name = name;  this.age = age; } public int getId() {  return id; } public void setId(int id) {  this.id = id; } public String getName() {  return name; } public void setName(String name) {  this.name = name; } public int getAge() {  return age; } public void setAge(int age) {  this.age = age; }  @Override public String toString() {  return "id = " + id + ", name " + name + ", age = " + age; } }

3.新建一个SAXforHandler类继承DefaultHandler,而DefaultHandler实现了ContentHandler接口,需要重写我们需要的方法

package com.example.xml_parser;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;import org.xml.sax.Attributes;import org.xml.sax.InputSource;import org.xml.sax.SAXException;import org.xml.sax.XMLReader;import org.xml.sax.helpers.DefaultHandler;import android.util.Log;public class SAXforHandler extends DefaultHandler private static final String TAG = "SAXforHandler"/**  * 用来存放解析的Person对象  */ private List<Person> persons;  /**  * Person 对象的引用,记录当前的Person  */ private Person person;  /**  * 通过此变量,记录当前一个标签的名称  */ private String tag ;  /**  * 此方法只有在开始解析文档的时候执行一次,比较适合处理一些初始化的东西  * 我new 了一个ArrayList<Person>()对象和打印Log  */ @Override public void startDocument() throws SAXException {  persons = new ArrayList<Person>();  Log.i(TAG, "****startDocument*****"); } /**  * 文档解析完了调用的回调方法  */ @Override public void endDocument() throws SAXException {  Log.i(TAG, "****endDocument*****"); } /**  * uri 是命名空间  * localName 标签的名称,如name, age 等  * qName 带命名空间的标签名  * Attributes 存放改标签的所有属性  *   * 当localName为person的时候, 我们拿出 person标签的属性值,此处由于只有一个属性,也可以直接person.setId(Integer.valueOf(attributes.getValue(0)));  * 然后设置tag = person,这个方法执行完了,然后会执行回调方法characters(char[] ch, int start, int length),这是一个循环的过程  */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {  if("person".equals(localName)){   for(int i=0; i<attributes.getLength(); i++){    Log.i(TAG, "attributesName: " + attributes.getLocalName(i) + "__attributesValue: " + attributes.getValue(i) );    person = new Person();    person.setId(Integer.valueOf(attributes.getValue(i)));   }  }    tag = localName;  Log.i(TAG, "localName = " + localName); }  /**  * 这个方法只要是获取两个标签里面的值的,这里最好用trim()方法过滤下,可以避免读取到的XML有空格带来不必要的麻烦  * 执行完这个方法就执行回调方法endElement(String uri, String localName, String qName),这也是一个循环的过程  */ @Override public void characters(char[] ch, int start, int length)   throws SAXException {  String date = new String(ch, start, length).trim();  if(!"".equals(date)){   Log.i(TAG, "Content: " + date);  }  if("name".equals(tag)){   person.setName(date);  }else if("age".equals(tag)){   person.setAge(Integer.valueOf(date));  } }   /**  * uri ,localName, qName跟上面的一个意思  * 当localName = person 并且person对象为 null时 ,说明一个person对象解析完毕  * 将person加入到List当中  * 每个标签解析完了需要将tag = null  */ @Override public void endElement(String uri, String localName, String qName)   throws SAXException {  if("person".equals(localName) && person != null){   persons.add(person);   person = null;  }    tag = null; }  /**  * 拿到成员变量List<Person> persons的方法  * @return  */ public List<Person> getPersons() {  return persons; } /**  * 1.加载需要解析的文件,因为XML放在src目录下,可以通过类装载器的方法获得文件路径,在以输入流的方式加入解析器  * 2.解析XML有两种形式,创建一个XMLReader 或者直接使用XMLParser  * @return  * @throws Exception  */ public static List<Person> sax_XML() throws Exception{  InputStream is = MainActivity.class.getClassLoader().getResourceAsStream("android.xml");    /** 坑爹的地方,当我调用getInputStreamContent (InputStream is)这个方法时,解析就错误,不知道为什么???*/    SAXforHandler saXforHandler = new SAXforHandler();  SAXParserFactory spf = SAXParserFactory.newInstance();  SAXParser saxParser = spf.newSAXParser();    //使用XMLReader的方式//  XMLReader xmlReader = saxParser.getXMLReader();//  xmlReader.setContentHandler(saXforHandler);//  xmlReader.parse(new InputSource(is));    //直接使用XMLParser,推荐使用这种  saxParser.parse(is, saXforHandler);    //获取解析好了的List对象  List<Person> list = saXforHandler.getPersons();  is.close();  return list; }   /**  * 测试方法,根据输入流获取里面的内容  * @param is  * @return  * @throws IOException  */ public static String getInputStreamContent (InputStream is) throws IOException{  StringBuffer sb = new StringBuffer();  BufferedReader br = new BufferedReader(new InputStreamReader(is));  String line;  while((line = br.readLine()) != null){   sb.append(line);  }  br.close();    Log.i(TAG, sb.toString());    return sb.toString(); }}

我只是调用那个方法就错误

org.apache.harmony.xml.ExpatParser$ParseException: At line 1, column 0: no element foundat org.apache.harmony.xml.ExpatParser.finish(ExpatParser.java:550)at org.apache.harmony.xml.ExpatParser.parseDocument(ExpatParser.java:480)at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:318)at org.apache.harmony.xml.ExpatReader.parse(ExpatReader.java:275)at javax.xml.parsers.SAXParser.parse(SAXParser.java:390)at javax.xml.parsers.SAXParser.parse(SAXParser.java:187)at com.example.xml_parser.SAXforHandler.sax_XML(SAXforHandler.java:146)at com.example.xml_parser.TestForXML.testSax_XML(TestForXML.java:7)at java.lang.reflect.Method.invokeNative(Native Method)at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:529)at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1448)

那位大牛知道是什么情况,我又没有改变InputStream,为什么会出现异常,求大牛赐教,好了,洗澡睡觉去了,希望明天早上看到大牛为我解答

DOM解析XML

Pull解析XML

 

           
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值