XML 之解析之SAX解析器

本文介绍了如何在Java中使用SAX解析XML文档,包括获取SAX解析器工厂,解析器实例化,将XML转化为输入流,以及详细解释了startDocument、endDocument、startElement、endElement和characters等事件处理方法。

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

一、        前言



用 Java解析XML文档,最常用的有两种方法:使用基于事件的XML简单API(Simple API for XML)称为SAX和基于树和节点的文档对象模型(Document Object Module)称为DOM。Sun公司提供了Java API for XML Parsing(JAXP)接口来使用SAX和DOM,通过JAXP,我们可以使用任何与JAXP兼容的XML解析器。


JAXP接口包含了三个包:


(1)       org.w3c.dom  W3C推荐的用于XML标准规划文档对象模型的接口。


(2)       org.xml.sax   用于对XML进行语法分析的事件驱动的XML简单API(SAX)


(3)       javax.xml.parsers解析器工厂工具,程序员获得并配置特殊的特殊语法分析器。
javax包 相对于 java包 占用资源比较少

二、        前提



DOM编程不要其它的依赖包,因为JDK里自带的JDK里含有的上面提到的org.w3c.dom、org.xml.sax 和javax.xml.parsers包就可以满意条件了。


三、        使用SAX解析XML文档



SAX是基于事件的简单API,同样的我们也是用一个最简单的例子来看看SAX是如何解析XML的


先来看看我们要解析的XML代码吧


<?xml version="1.0" encoding="gb2312"?>


<books>


  <book email=“alexlee”>


             <name addr="address">kunshan</name>


             <price>10</price>


  </book>


</books>


简单的不能再简单了。但是该有的都有了,根元素、属性、子节点。好了,能反应问题就行了,下面来看看解析这个XML文件的Java代码吧!




这段代码比较短,因为SAX是事件驱动的,它的大部分实现在在另一个Java文件中,先别管另一个文件,我们来一个个地分析吧!


(1)得到SAX解析器的工厂实例



3            SAXParserFactory saxfac=SAXParserFactory.newInstance();


这是一个javax.xml.parsers.SAXParserFactory类的实例


(2)从SAX工厂实例中获得SAX解析器



5            SAXParser saxparser=saxfac.newSAXParser();


使用javax.xml.parsers.SAXParserFactory工厂的newSAXParser()方法


(3)把要解析的XML文档转化为输入流,以便DOM解析器解析它



6                   InputStream is=new FileInputStream("bin/library.xml");


InputStream是一个接口。


(4)解析XML文档



7                   saxparser.parse(is,new MySAXHandler());


后面就不用看了,都是些没用的代码(相对而言),够简单的吧!


注意了,我们新建了一个实例new MySAXHandler()这个实例里面又有什么东西呢?


这个实例就是SAX的精华所在。我们使用SAX解析器时,必须实现内容处理器ContentHandler接口中的一些回调方法,然而我们不须要全部地实现这些方法,还好,我们有org.xml.sax.helpers.DefaultHandler类,看它的类申明:


public class DefaultHandler


implements EntityResolver, DTDHandler, ContentHandler, ErrorHandler


实现了这么多接口啊,其它的先不管了,至少它实现了ContentHandler这一接口。




不要看它一大堆,我一一分解给大家看。我们说SAX是基于事件的API,我们这个类实到了ContentHandler接口中的如下方法:


(1)startDocument()  用于处理文档解析开始事件

    只被执行一次


     public void startDocument() throws SAXException {


               System.out.println("文档开始打印了");


        }


(2)endDocument()  用于处理文档解析结束事件

    只被执行一次
      public void endDocument() throws SAXException {


              System.out.println("文档打印结束了");


        }


(3)startElement  用于处理元素开始事件

    遇到开始标签被触发
     public void startElement(String uri, String localName, String qName,


                     Attributes attributes) throws SAXException {


              if(qName.equals("books")){


                     return;


              }


              if(qName.equals("book")){


                     System.out.println(attributes.getQName(0)+attributes.getValue(0));


              }


              if(attributes.getLength()>0){


                     this.attributes=attributes;


                     this.hasAttribute=true;


              }


       }


第二个参数String qName表示这个元素的名字,如:


根节点 <books></books> 它的qName为“books”


最底层节点 <price>jjjjjj</price> 它的qName为“price”


知道这一点上面程序就好解释了,当遇到根元素“books”时就什么也不做跳过,当遇到“book”元素时就打出它的属性(它只有一个属性<book email="zhoujunhui"></book>)。


当是其它节点时(这下只剩下最底层的两个节点“name”和“price”了),就把它的属性取出来存到this.attributes域中,以后中元素结束事件好处理。


(4)endElement 用于处理元素结束事件

    遇到结束标签被触发
     public void endElement(String uri, String localName, String qName)


                     throws SAXException {


              if(hasAttribute&&(attributes!=null)){


                     for(int i=0;i<attributes.getLength();i++){


                            System.out.println(attributes.getQName(0)+attributes.getValue(0));


                     }


              }


       }


代码的作用是如果这个元素的属性不为空(hasAttribute&&(attributes!=null)),就把它们打印出来。


(5)characters(char[] ch, int start, int length) 处理元素字符的内容

    <></> 之间遇到任何 "回车符" "空格符"或其他"不为空"的字符
    都将触发characters 方法,两个标签之间的部分,不论有多少
    空格 回车 字符  都只能触发一次characters方法
charachers(char [] ch,int start,int length):当遇到xml内容时触发这个方法,
用new String(ch,start,length)可以接受内容
              public void characters(char[] ch, int start, int length)


                     throws SAXException {


              System.out.println(new String(ch,start,length));


       }



public class SaxXml {

	public static void main(String[] args) {
		
		SAXParserFactory saxFactory = SAXParserFactory.newInstance();
		
		try {
			SAXParser parser = saxFactory.newSAXParser();
			File file = new File("src/com/xm/inproe.xml");
			parser.parse(file, new MyHander());
			
			
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
				
	}
}


class MyHander extends DefaultHandler{
	@Override
	public void characters(char[] ch, int start, int length) throws SAXException {
	
		String a = new String(ch, start, length);
		System.out.print(a);
	}
	@Override
	public void endElement(String uri, String localName, String qName) throws SAXException {

		System.out.print("</"+qName+">");
	}
	@Override
	public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

		System.out.print("<"+qName+"");
		for (int i = 0; i < attributes.getLength(); i++) {
			String name = attributes.getQName(i);
			String values = attributes.getValue(name);
			System.out.print(" "+name+"=“"+values+"”");
		}
		System.out.print(">");
	}
}


inproe.xml
<?xml version="1.0" encoding="UTF-8"?>
<employees>
    <employee id="1" depName="教学部">
       Text XMl sax
        <name>tom</name>
        <age>18</age>
        <gender>male</gender>
        <salary>200</salary>
        <test>test</test>
    </employee>
    
     <employee id="2" depName="教学部">
        <name>java</name>
        <age>19</age>
        <gender>famale</gender>
        <salary>2050</salary>
    </employee>
    
     <employee id="3" depName="市场部">
        <name>store</name>
        <age>20</age>
        <gender>famale</gender>
        <salary>4000</salary>
    </employee>
    
     
    <employee id="4" depName="市场部">
        <name>buy</name>
        <age>21</age>
        <gender>male</gender>
        <salary>45500</salary>
    </employee>
    
</employees>

控制台输出



































































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值