如何使用sax解析xml文档


  对xml的解析方法有多种,如sax、dom、pull,在这里我就简单介绍一下sax解析xml。

XML介绍:XML(Extensible Markup Language)即可扩展标记语言,它与HTML一样,都是SGML(标准通用标记语言)。

图解:

123部分统称为节点。

12部分应该称为Element,中文为元素。

3部分是TextNode文本节点。

4是属性与属性值。

SAX是一种以事件为驱动的XML API,由它定义的事件流可以指定从解析器传到专门的处理程序代码的XML结构。

事件接口

ContentHandler定义与文档本身关联的事件(例如,开始和结束标记)。大多数应用程序都注册这些事件。为简化工作,SAX在DefaultHandler类中提供了这些接口的默认实现。

在大多数情况下,为应用程序扩展DefaultHandler并覆盖相关的方法要比直接实现一个接口更容易。

ContentHandler是最常用的SAX接口,我们主要掌握以下5种方法

startDocument()/endDocument()通知应用程序文档的开始或结束。

startElement()/endElement() 通知应用程序元素的开始或结束。

characters() 当语法分析器在元素中发现文本(已经解析过的字符数据)时。

属性作为Attributes参数传递,在startElement()事件中应用

Attributes定义下列方法:

getValue(i)/getValue(qName)/getValue(uri,localName)返回第i个属性值或给定名称的属性值。

getLength()返回属性长度。

getQName(i)/getLocalName(i)/getURI(i)返回限定名(带前缀)、本地名(不带前缀)和第i个属性的名称空间URI。

第一步:

针对从XML中需要获得信息,需要对其新建一个Student类,存放相关信息。

第二步:

新建一个类继承自DefaultHandler,而DefaultHandler是实现了ContenHandler 的接口。因为该接口中没有方法体所以可直接继承它的子类DefaultHandler

在菜单中选取Source,选择Override/ImplementMethods,选取需要重写的方法。

SaxHandler.java

package com.abc.json;

import java.util.ArrayList;
import java.util.List;

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

import android.util.Log;

import com.abc.student.student;

public class SaxHandler extends DefaultHandler {
  private  List<student> students=null;
  private String TAG="SaxHandler";
  private student s=null;//记录当前student 
  private String sName=null;//自定义一个标签 通过此变量,记录前一个标签的名称
	
	public List<student> getStudents() {
	return students;
}

public void setStudents(List<student> students) {
	this.students = students;
}

	@Override
	public void startDocument() throws SAXException {
		// TODO Auto-generated method stub
		super.startDocument();
		Log.v(TAG, "$$$$$-----startDocument----$$$$");
		students = new ArrayList<student>();// 适合在此事件中触发初始化行为
	}
	

	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		// attributes:属性、uri:命名空间、localName当前标签
		super.startElement(uri, localName, qName, attributes);
		Log.v(TAG, "$$$$$-----startElement----$$$$");
		
		if ("student".equals(localName)) {
			s=new student();
			s.setId(attributes.getValue(0));//获取第一个属性并设置id
			Log.v(TAG, "attributeName:"+attributes.getLocalName(0)+"attribute_Value:"+attributes.getValue(0));
		}
		sName=localName;
	}
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		// 文本节点(name、age)
		super.characters(ch, start, length);
		Log.v(TAG, "$$$$$-----characters----$$$$");
		
		String values=new String(ch, start, length);//通过有参构造方法将字节数组转换成字符串
		
		if (sName.equals("name")) {
			s.setName(values);
		}else if (sName.equals("age")) {
			s.setAge(Integer.valueOf(values));//将字符串强转为整形
			
		}	
	//判空
		if(!values.equals("")){
			Log.v(TAG, "content"+values);
		}
	}
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		// TODO Auto-generated method stub
		super.endElement(uri, localName, qName);
		Log.v(TAG, "$$$$$-----endElement----$$$$");
		if (localName.equals("student")) {//结束标签student
			students.add(s);//把一个解析好的对象加入集合中,在进行下一个解析,并将student对象与自定义标签赋值为空
			s=null;		
		}
		sName=null;
	}

	@Override
	public void endDocument() throws SAXException {
		// TODO Auto-generated method stub
		super.endDocument();
		Log.v(TAG, "$$$$$-----endDocument----$$$$");
	}

}

注:

关于要获取当前TextNode,可以使用new String(ch,start,length).trim()

这里最好对得到的字符串使用trim()方法过滤一下,可以避免读取到的XML有空格时,因为格式不整齐,造成不必要的麻烦。

对Handler中相应参数的解释:

startElement( String namespaceURI, String localNameString fullName,Attributes attribu) 

namespaceURI:命名空间;

localName:标签名称,即示例中的mx;

Attributes:存放该标签的所有属性。

characters(char[] ch, int start, int length) 

ch:当前读取到的TextNode(将文本字符串代表为文档层次中的结点,即文本节点)字节数组;

start:字节开始的位置,如果要读取全部,那就是从0开始;

length:当前TextNode的长度。

xml:

<?xml version="1.0" encoding="utf-8"?>
<students> 
    
    <student id=14105244>
        <name>mx</name>
        <age>20</age>
    </student>
    
    <student id=14105203>
        <name>wh</name>
        <age>45</age>
    </student>
    
    <student id=14105231>
        <name>yeb</name>
        <age>46</age>
    </student>
    
</students>

针对从 XML 中需要获得信息,需要对其新建一个 Student 类,存放相关信息。 

student.java

package com.abc.student;

public class student {
	private String id;
	private String name;
	private int age;

	public String getId() {
		return id;
	}
	public void setId(String 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;
	}
	public student(String id, String name, int age) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
	}
	public student() {
		super();
	}
	@Override
	public String toString() {
		return "student [id=" + id + ", name=" + name + ", age=" + age + "]";
	}
}

n 解析 XML 有两种形式,需要创建一个 XMLReader 或者直接使用 SAXParser
n 使用: XMLReader,代码中使用了SAXParser
XMLReader xmlReader = saxParser.getXMLReader();  
xmlReader.setContentHandler(handler);  
xmlReader.parse(new InputSource(is)); 

StudentTest.java
package com.abc.json;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
import com.abc.student.student;
import android.test.AndroidTestCase;
import android.util.Log;
//创建单元测试类
public class StudentTest extends AndroidTestCase {
	//必须继承AndroidTestCase才可以使用JUnit进行测试
	public static final String TAG="StudentTest";
	//这里有一个不成文的规定,创建的类必须以test开头
      public void TestParser() throws ParserConfigurationException, SAXException, IOException {
    	  //加载需要解析的文件。
		InputStream is=this.getClass().getClassLoader().getResourceAsStream("xas.xml");
		//加载自己创建的处理类对象,并通过一个SAXParserFactory来创建具体SaxParser。
		SAXParserFactory spf=SAXParserFactory.newInstance();
		SAXParser  saxparser=spf.newSAXParser();
		
		SaxHandler shandler=new SaxHandler();
		//使用SAXParser解析xml。
		saxparser.parse(is, shandler);
		is.close();
	    List<student> sList=	shandler.getStudents();
	    
	    for (student student : sList) {
			Log.v(TAG, student.toString());
		}
	}
}


最后对代码将使用JUnit进行测试

此时为了方便观察单元测试和SAX内部的测试过程,分别在LogCat中加入两个过滤器"StudentTest""SaxHandler"





猜你喜欢

转载自blog.csdn.net/mxcsdn/article/details/50827809