`
king_tt
  • 浏览: 2232841 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

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

    博客分类:
  • xml
阅读更多

今天晚上我学习了下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 found
at 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

 

分享到:
评论

相关推荐

    android学习笔记1--SAX解析XML

    ### Android学习笔记1—SAX解析XML #### SAX解析XML概览 在Android开发中,XML文件被广泛用于布局设计、资源定义等场景。而为了处理这些XML文件,开发者需要了解不同的XML解析技术,其中SAX(Simple API for XML)...

    SAX解析XML文件实例

    一个项目同时用dom解析和sax解析xml文件貌似会报错,项目框架建一直是用sax和dom4j解析xml文件的。当我用dom解析xml文件。导入包后就报错识别不了xml文件的编码格式。于是做了一个sax解析xml文件的实例

    java解析xml数据---sax解析器

    以下是一个简单的SAX解析示例,以处理名为`person.xml`的文件为例: ```java import javax.xml.parsers.*; import org.xml.sax.*; import org.xml.sax.helpers.*; public class PersonHandler extends ...

    Sax解析XML文件解析

    2. **设置事件处理器**:通过`SAXParser`的`setHandler`方法设置一个实现了`ContentHandler`接口的对象,这个对象将处理SAX解析过程中触发的事件。 3. **解析XML**:调用`parse`方法,传入XML文件的输入流或URL,...

    dom-sax解析XML文件-java

    DOM解析器将整个XML文件加载到内存中,构建一个树形结构,即DOM树。每个XML元素、属性和文本节点都对应于DOM树中的一个对象。这种解析方式的主要优点是可以方便地通过节点关系进行任意遍历和修改,因为所有数据都在...

    读取RSS-SAX解析XML实例(java版)

    而SAX(Simple API for XML)是一种事件驱动的XML解析器,它不像DOM(Document Object Model)那样将整个XML文档加载到内存中,而是逐行解析,因此对于大型XML文件,SAX解析更高效。 标题"读取RSS-SAX解析XML实例...

    Sax解析xml文件

    以下是一个使用SAX解析XML文件的基本步骤: 1. **创建解析器**: 首先,我们需要创建一个SAX解析器实例。在Java中,这通常通过`SAXParserFactory`类完成。设置解析器属性,然后调用`newSAXParser()`方法获取`...

    sax解析xml文件

    总结来说,"saxloadxml"项目提供了使用SAX解析XML文件的一个实例,可以帮助开发者了解如何利用SAX解析器处理XML文档,尤其是在性能和内存使用方面有较高要求的情况下。通过学习和实践这个项目,你可以提升处理XML...

    Android网络之数据解析----SAX方式解析XML数据

    1. 创建XML解析器:首先,我们需要创建一个XMLReader对象,它是SAX解析器的接口,可以通过XMLReaderFactory类来实例化。 2. 设置事件处理器:然后,我们为XMLReader对象设置一个ContentHandler,这是一个接口,包含...

    SAX解析超大XML文件 示例代码

    以下是一个简单的SAX解析超大XML文件的Java示例代码: ```java import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import javax.xml.parsers....

    Java SAX解析Xml文档Demo

    然后,我们创建一个主类,用于初始化SAX解析器并开始解析XML文档。 ```java import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import java.io.File; public class SaxDemo { ...

    [Android]使用SAX解析XML文件

    总结,SAX解析XML在Android开发中是一个实用且高效的解决方案,尤其适用于处理大型XML文件。通过创建自定义的事件处理器,可以灵活地解析和处理XML数据,满足各种业务需求。不过,需要注意的是,由于SAX是基于事件的...

    java-SAX解析XML、java正则表达式.

    Java编程语言在处理XML数据时提供了多种方法,其中SAX(Simple API for XML)解析器是一种基于事件驱动的解析方式,适用于处理大型XML文件。它不会一次性加载整个XML文档到内存,而是逐行读取,当遇到XML元素的开始...

    SAX解析xml文件源码

    开发者需要创建一个实现了SAX解析器回调接口的类,当解析器遇到这些事件时,会调用相应的方法,将XML内容传递给用户代码处理。 **SAX解析的工作流程:** 1. 创建SAX解析器:通过`SAXParserFactory`工厂类获取`...

    Servlet利用SAX解析XML文档

    5. **实现ContentHandler**:创建一个实现了`org.xml.sax.ContentHandler`接口的类,覆盖其中的方法,如`startElement()`, `endElement()`, `characters()`等,这些方法会在解析过程中被调用。 6. **配置和启动解析...

    sax解析xml尤其是获取元素的值或者内容

    在使用SAX解析XML前,需要创建一个解析器实例。Java中,可以使用`SAXParserFactory`来生成`SAXParser`,然后调用`parse()`方法解析XML文件。例如: ```java SAXParserFactory factory = SAXParserFactory.new...

    sax解析xml本地读取xml

    以下是一个简单的SAX解析XML文件的Java代码示例: ```java import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler;...

Global site tag (gtag.js) - Google Analytics