如何使用sax解析xml文档

来源:互联网 发布:五常大米价格 知乎 编辑:程序博客网 时间:2024/06/05 11:03


  对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;}@Overridepublic void startDocument() throws SAXException {// TODO Auto-generated method stubsuper.startDocument();Log.v(TAG, "$$$$$-----startDocument----$$$$");students = new ArrayList<student>();// 适合在此事件中触发初始化行为}@Overridepublic 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));//获取第一个属性并设置idLog.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);}}@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {// TODO Auto-generated method stubsuper.endElement(uri, localName, qName);Log.v(TAG, "$$$$$-----endElement----$$$$");if (localName.equals("student")) {//结束标签studentstudents.add(s);//把一个解析好的对象加入集合中,在进行下一个解析,并将student对象与自定义标签赋值为空s=null;}sName=null;}@Overridepublic void endDocument() throws SAXException {// TODO Auto-generated method stubsuper.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();}@Overridepublic 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"





2 0
原创粉丝点击