解析XML专题之SAX方式

本文深入探讨了SAX解析XML的原理与实现,对比DOM解析,SAX更快速且节省资源,尤其适合处理大型XML文件。文章详细介绍了SAX解析器的创建与使用流程,通过代码示例展示了如何定制Handler类以捕获XML解析过程中的各种事件。

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

解析XML专题之SAX方式

 

SAX和DOM解析的不同原理

DOM解析: 是一次性加载文件所有内容到内存中,并构建一个驻留在内存的树状结构(节点数),如果需要解析的xml文档过大,或我们只需要对文档部分内容感兴趣,会引起性能问题

 

SAX解析: 是逐行扫描文档,一边扫描,一边解析。

与DOM相比, SAX方法更快速,更有效,可以在解析的任何时刻停止解析,但是它的缺点就是实现太复杂。

 

SAX实现步骤

  • 首先SAXParseFactory 来创建一个SAXParserFactory实例

SAXParserFactory factory = SAXParserFactory.newInstance();

  • 根据SAXParserFactory实例来创建SAXParser

SAXParserHandler hanlder = new SAXParserHandler();

parser.parse("test.xml", hanlder);

 

在入口代码处如下:

                // 获取SAXParserFactory实例
		SAXParserFactory factory = SAXParserFactory.newInstance();
		// 获取SAXParser 实例
		SAXParser parser;
		try {
			parser = factory.newSAXParser();
			SAXParserHandler hanlder = new SAXParserHandler();
			parser.parse("test.xml", hanlder);
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ParserConfigurationException e1) {
			e1.printStackTrace();
		}
  • 在解析过程中触发相对于接口中的事件处理程序

创建自定义Handler类继承DefaultHanlder, 通过下面的方法重写来进行事件处理

如下代码所示:

public class SAXParserHandler extends DefaultHandler {
      int studentsIndex=0;
	/*
	 * 当遇到开始标记时调用
	 * qName 表示扫描的开始标记的名字
	 */
	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
		super.startElement(uri, localName, qName, attributes);
		if(qName.equals("student")) {
			studentsIndex++ ;
			System.out.println("开始遍历 第 "+studentsIndex + "个 student ");
			//已知student标记下的属性个数以及属性名,可以通过如下方法获取属性值
			String value = attributes.getValue("id");
			System.out.println("开始标记 " + qName + "的属性值" + value);
			
			//如果不确定属性个数和属性名,采用下面的方法来遍历
			int num = attributes.getLength();
			for(int i = 0 ; i < num ; i++) {
				System.out.print("开始遍历第" + (i + 1 ) + "个属性 : " + attributes.getQName(i) );
				System.out.println(" = " + attributes.getValue(i));
			}
		}else {
			System.out.print ("节点名:"+qName);
		}
		
		
	}
	
	
	/*
	 * 获取节点值的方法 (当分析器遇到无法识别为标记或者指令类型字符时调用)
	 * ch所有文档内容除了节点之外
	 */
	
	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
		super.characters(ch, start, length);
		String value = new String(ch, start, length);
		if(!value.trim().equals("")) {
			System.out.println(" = " + value);
		}
		
		
	}



	/*
	 * 当遇到节点结束时调用
	 */
	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {
		// TODO Auto-generated method stub
		super.endElement(uri, localName, qName);
		if(qName .equals("student")) {
			System.out.println("--------------------结束扫描标记第" + studentsIndex +" student-----------------");
		}
		
	}
	
	/*
	 * 文件打开时调用
	 */
	@Override
	public void startDocument() throws SAXException {
		// TODO Auto-generated method stub
		super.startDocument();
		System.out.println("xml文档解析开始");
	}
	
	/*
	 * 当到文档的末尾调用
	 */
	@Override
	public void endDocument() throws SAXException {
		// TODO Auto-generated method stub
		super.endDocument();
		System.out.println("xml文档解析结束");
	}
	
}

运行结果如下:
 

xml文档解析开始
节点名:students开始遍历 第 1个 student 
开始标记 student的属性值1
开始遍历第1个属性 : id = 1
节点名:name = zhangsan
节点名:age = 20
--------------------结束扫描标记第1 student-----------------
开始遍历 第 2个 student 
开始标记 student的属性值2
开始遍历第1个属性 : id = 2
节点名:name = lisi
节点名:age = 25
--------------------结束扫描标记第2 student-----------------
xml文档解析结束

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值