SAX解析XML

SAX,全称Simple API for XML,是一种以事件驱动的XMl API,是XML解析的一种新的替代方法,解析XML常用的还有DOM解析,PULL解析(Android特有)。
SAX与DOM不同的是,SAX解析方式会逐行地去扫描XML文档,当遇到标签时会触发解析处理器,采用事件处理的方式解析XML 。在读取文档的同时即可对XML进行处理,不必等到文档加载结束,相对快捷。不需要加载进内存,因此不存在占用内存的问题,可以解析超大XML。所以它解析XML具有速度快,占用内存少的优点,对于Android等CPU资源宝贵的移动平台来说是一个巨大的优势。缺点是:只能用来读取XML中数据,无法进行增删改。

  • SAX解析的优点
    1. 解析速度快。
    2. 占用内存少。
  • SAX解析的缺点
    1. 无法知道当前解析标签(节点)的上层标签,及其嵌套结构,仅仅知道当前解析的标签的名字和属性。
    2. 只能读取XML中数据,无法进行增删改。
    3. 无法随机访问某个标签(节点)。

SAX解析xml的步骤:

  1. 得到xml文件对应的资源,可以是xml的输入流,文件和uri。
BufferedInputStream bufStream = getConfigStream(name);
  1. 得到SAX解析工厂(SAXParserFactory)。
SAXParserFactory parserFactory = SAXParserFactory.newInstance();
  1. 由解析工厂生产一个SAX解析器(SAXParser)。
SAXParser parser = parserFactory.newSAXParser();
  1. 传入输入流和handler给解析器,调用parse()解析。
ConfigHandler configHandler =
        new ConfigHandler(
                configDef, name, mConfigDefLoader, mParentDeviceObject, templateMap);
parser.parse(new InputSource(xmlInput), configHandler);

Handler的5个主要的回调方法:
用SAX解析XML文档的时候,在读取到文档开始和结束标签时候就会回调一个事件,在读到其他节点与内容的时候也会回调一个事件。
2. startDocument() 文档解析开始事回调
3. startElement(String uri, String localName, String qName, Attributes attributes) 读取到节点的开始标签时回调
1. uri:xml文档的命名空间
2. localName:标签的名字
3. qName:带命名空间的标签的名字
4. attributes:标签的属性集
4. characters(char[] ch, int start, int length)读取到标签的内容时回调
1. ch:当前读取到的TextNode(文本节点)的字节数组
2. start:字节开始的位置,为0则读取全部
3. length:当前TextNode的长度
5. endElement(String uri, String localName, String qName)读取到节点的结束标签时回调
6. endDocument()文档解析结束时回调

sax simple API for XML,现在有两个版本:

  1. sax. 不支持LocalName、QName和uri。对于属性sina:blog=“blog.sina.com”,sax解析的结果是LocalName=QName=“sina:blog”,uri="",value=“blog.sina.com”。
  2. sax2. 支持LocalName、QName、uri。对于属性sina:blog=“blog.sina.com”,sax2解析的结果是LocalName=“blog”,QName=“sina:blog”,uri="",value=“blog.sina.com”。

SAX的实现方式:

import java.io.StringReader;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class XmlSaxParser {
	public static void main(String... args) {
		try {
		    String config
		            = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                    + "<websites"
                    + "    xmlns:sina=\"http://www.sina.com\""
                    + "    xmlns:baidu=\"http://www.baidu.com\">"
                    + "    <sina:website sina:blog=\"blog.sina.com\">新浪</sina:website>"
                    + "    <baidu:website baidu:blog=\"hi.baidu.com\">百度</baidu:website>"
                    + "</websites>";
			//sax1解析XML文档
			System.out.println("parse xml file use sax");
			SaxParseHandler saxHandler = new SaxParseHandler();
			SAXParserFactory factory=SAXParserFactory.newInstance();
			SAXParser parser = factory.newSAXParser();
	        parser.parse(new InputSource(new StringReader(config)), saxHandler);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}
}

class SaxParseHandler extends DefaultHandler{
	/**
	 * 重写了DefaultHandler中的startElement函数,每解析到
	 * 一个元素(element)的时候都会触发这个函数,并且将这个element
	 * 的属性attributes和值value当作参数传进来。除了startElement,
	 * 还有startDocument,endDOucment,endElement,要根据需要
	 * 重写这些函数。
	 */
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		//打印element的基本信息,qName
		System.out.println("Element qName    : "+qName);
		System.out.println("Element localName: "+localName);
		System.out.println("Element uri      : "+uri);
		//打印element的所有属性attributes
		for(int i=0; i<attributes.getLength(); i++) {
			System.out.println("");
			System.out.println("  attribute qName    : "+attributes.getQName(i));
			System.out.println("  attribute localName: "+attributes.getLocalName(i));
			System.out.println("  attribute value    : "+attributes.getValue(i));
			System.out.println("  attribute uri      : "+attributes.getURI(i));
		}
		System.out.println("");
		super.startElement(uri, localName, qName, attributes);
	}
}

SAX2的第一种实现方式:

import java.io.StringReader;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class XmlSaxParser {
	public static void main(String... args) {
		try {
		    String config
		            = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                    + "<websites"
                    + "    xmlns:sina=\"http://www.sina.com\""
                    + "    xmlns:baidu=\"http://www.baidu.com\">"
                    + "    <sina:website sina:blog=\"blog.sina.com\">新浪</sina:website>"
                    + "    <baidu:website baidu:blog=\"hi.baidu.com\">百度</baidu:website>"
                    + "</websites>";
			//sax1解析XML文档
			System.out.println("parse xml file use sax");
			SaxParseHandler saxHandler = new SaxParseHandler();
			SAXParserFactory factory=SAXParserFactory.newInstance();
			factory.setNamespaceAware(true);
			SAXParser parser = factory.newSAXParser();
	        parser.parse(new InputSource(new StringReader(config)), saxHandler);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}
}

class SaxParseHandler extends DefaultHandler{
	/**
	 * 重写了DefaultHandler中的startElement函数,每解析到
	 * 一个元素(element)的时候都会触发这个函数,并且将这个element
	 * 的属性attributes和值value当作参数传进来。除了startElement,
	 * 还有startDocument,endDOucment,endElement,要根据需要
	 * 重写这些函数。
	 */
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		//打印element的基本信息,qName
		System.out.println("Element qName    : "+qName);
		System.out.println("Element localName: "+localName);
		System.out.println("Element uri      : "+uri);
		//打印element的所有属性attributes
		for(int i=0; i<attributes.getLength(); i++) {
			System.out.println("");
			System.out.println("  attribute qName    : "+attributes.getQName(i));
			System.out.println("  attribute localName: "+attributes.getLocalName(i));
			System.out.println("  attribute value    : "+attributes.getValue(i));
			System.out.println("  attribute uri      : "+attributes.getURI(i));
		}
		System.out.println("");
		super.startElement(uri, localName, qName, attributes);
	}
}

SAX2的第二种实现方式(deprecated API):

import java.io.StringReader;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class XmlSaxParser {
	public static void main(String... args) {
		try {
		    String config
		            = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                    + "<websites"
                    + "    xmlns:sina=\"http://www.sina.com\""
                    + "    xmlns:baidu=\"http://www.baidu.com\">"
                    + "    <sina:website sina:blog=\"blog.sina.com\">新浪</sina:website>"
                    + "    <baidu:website baidu:blog=\"hi.baidu.com\">百度</baidu:website>"
                    + "</websites>";
			//Sax2解析XML文档
			System.out.println("parse xml file use sax2");
			SaxParseHandler sax2Handler = new SaxParseHandler();
			XMLReader xmlReader = XMLReaderFactory.createXMLReader();
			xmlReader.setContentHandler(sax2Handler);
			StringReader fileReader = new StringReader(config);
			xmlReader.parse(new InputSource(fileReader));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}
}


class SaxParseHandler extends DefaultHandler{
	/**
	 * 重写了DefaultHandler中的startElement函数,每解析到
	 * 一个元素(element)的时候都会触发这个函数,并且将这个element
	 * 的属性attributes和值value当作参数传进来。除了startElement,
	 * 还有startDocument,endDOucment,endElement,要根据需要
	 * 重写这些函数。
	 */
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		//打印element的基本信息,qName
		System.out.println("Element qName    : "+qName);
		System.out.println("Element localName: "+localName);
		System.out.println("Element uri      : "+uri);
		//打印element的所有属性attributes
		for(int i=0; i<attributes.getLength(); i++) {
			System.out.println("");
			System.out.println("  attribute qName    : "+attributes.getQName(i));
			System.out.println("  attribute localName: "+attributes.getLocalName(i));
			System.out.println("  attribute value    : "+attributes.getValue(i));
			System.out.println("  attribute uri      : "+attributes.getURI(i));
		}
		System.out.println("");
		super.startElement(uri, localName, qName, attributes);
	}
}


TF框架中,使用SAX2解析config文件。

import java.io.StringReader;
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;
public class XmlSaxParser  {

	/**
	 * 1.首先生成一个SAX解析器工厂实例
	 * 2.使用工厂来生成一个SAX解析器
	 * 3.生成XMLReader用来读取XML文件
	 * 4.在XMLReader对象上面注册内容事件处理程序
	 * 5.开始解析XML
	 **/
	public static void main(String[] args){
		try{
			String config
			        = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
			        + "<configuration description=\"Multi device parsing\">"
			        + "    <device name=\"device1\">"
			        + "        <build_provider class=\"com.android.tradefed.build.StubBuildProvider\">"
			        + "            <option name=\"build-id\" value=\"10\" />"
			        + "        </build_provider>"
			        + "    </device>"
			        + "    <device name=\"device2\" >"
			        + "        <build_provider class=\"com.android.tradefed.build.StubBuildProvider\" />"
			        + "        <target_preparer class=\"com.android.tradefed.targetprep.StubTargetPreparer\" />"
			        + "    </device>"
			        + "    <device name=\"device3\" >"
			        + "        <build_provider class=\"com.android.tradefed.build.StubBuildProvider\">"
			        + "            <option name=\"build-flavor\" value=\"build-flavor3\" />"
			        + "        </build_provider>"
			        + "        <target_preparer class=\"com.android.tradefed.targetprep.StubTargetPreparer\" />"
			        + "        <target_preparer class=\"com.android.tradefed.targetprep.DeviceWiper\">"
			        + "            <option name=\"disable\" value=\"true\" />"
			        + "        </target_preparer>"
			        + "    </device>"
			        + "    <template-include name=\"preparers\" default=\"empty\" />"
			        + "    <logger class=\"com.android.tradefed.log.FileLogger\" />"
			        + "    <test class=\"com.android.tradefed.config.StubOptionTest\">"
			        + "        <option name=\"option\" value=\"valueFromTestConfig\" />"
			        + "    </test>"
			        + "</configuration>";
			//生成SAX的解析器工厂的实例
			SAXParserFactory factory=SAXParserFactory.newInstance();
			factory.setNamespaceAware(true);
			SAXParser parser = factory.newSAXParser();
			//开始解析
			parser.parse(new InputSource(new StringReader(config)), new MyHandlerContent());
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}
/**
 * 内容事件的处理程序,继承自DefaultHandler。
 *
 */
class MyHandlerContent extends DefaultHandler{

	@Override
	public void startDocument() throws SAXException {
		super.startDocument();
		System.out.println("********************start parse config via SAX2********************");
	}
	@Override
	public void endDocument() throws SAXException {
		super.endDocument();
		System.out.println("********************end parse config via SAX2********************");
	}
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		super.startElement(uri, localName, qName, attributes);
		System.out.print("<" + localName);
		for(int i=0;i<attributes.getLength();i++){
			System.out.print(" " + attributes.getLocalName(i) + "=\"" + attributes.getValue(i) + "\"");
		}
		System.out.println(">");
	}

	@Override
	public void endElement(String uri, String localName, String qName)
		throws SAXException {
		super.endElement(uri, localName, qName);
		System.out.println("</" + localName + ">");
	}

	@Override
	public void characters(char[] ch, int start, int length)
		throws SAXException {
		super.characters(ch, start, length);
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值