SAX解析XML

由于SAX解析XML的方式优缺点已经在网上随处可见,此博客只记录一下用法。

第一步:
编写一个XML文件,名为people.xml,如下。

<peoples>
	<people id="1">
		<name>李四</name>
		<password>123456</password>
	</people>
	<people id="2">
		<name>张三</name>
		<password>174896</password>
	</people>
	<people id="3">
		<name>王五</name>
		<password>123</password>
	</people>

</peoples>

第二步:
新建一个pojo,用来存储xml中解析的数据:

public class People {
	private int id;
	private String name;
	private String password;
	
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	@Override
	public String toString() {
		return "People [id=" + id + ", name=" + name + ", password=" + password + "]";
	}
}

第三步:
新建一个XML解析处理器类,该类是XML解析的核心,需要继承DefaultHandler,并且需要重写五个方法。他们分别是:

	/**
	 * 文档开始时调用,只调用一次
	 */
	@Override
	public void startDocument() throws SAXException{
		super.startDocument();
	}
	
	/**
	 * 文档结束时调用
	 */
    @Override
    public void endDocument() throws SAXException{
    	super.endDocument();
    }

	  /**
     * 结点开始时调用
     * 主要用到的参数为qName和attributes。
     * qName为当前结点的名称
     * attributes为当前结点的属性值,根据索引可以取到(attributes.getValue(i))
     */
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
    }
	
	/**
	 * 结点结束时调用
	 * 一般 做结点结束时的收尾工作
	 */
	@Override
    public void endElement(String uri, String localName, String qName)
                throws SAXException{
    }
		
	/**
     * 该方法解析当前标签的内容,如<name>李四</name>,则获取“李四”
     */
	  @Override
        public void characters(char[] ch, int start, int length)
             throws SAXException{
             }

XMLParserHandler完整代码:

public class XMLParserHandler extends DefaultHandler{
	//最终的people列表
	private List<People> peopleList;
	//记录当前的people
	private People people;
	//记录当前结点名
	private String tagName;
	
	public List<People> getPeopleList() {
		return peopleList;
	}
	public void setPeopleList(List<People> peopleList) {
		this.peopleList= peopleList;
	}
	public void setPeople(People people) {
		this.people = people;
	}
	public String getCurrentTag() {
		return tagName;
	}
	public void setTagName(String tagName) {
		this.tagName = tagName;
	}
	
	
	@Override
	public void startDocument() throws SAXException{
		userList = new ArrayList<>();
	}
	
	
    @Override
    public void endDocument() throws SAXException{
    	super.endDocument();
    }
    
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
    	if(qName.equals("people")) {
    		people = new People();
    		people.setId(Integer.parseInt(attributes.getValue(0)));
    	}
    	//将当前结点名记录,供characters()方法和endElement()方法判断当前是哪个结点
    	this.tagName = qName;
    }
    
    /**
     * 
     */
    @Override
        public void characters(char[] ch, int start, int length)
             throws SAXException{
    	//截取标签内字段值
    	String value = new String(ch,start,length);
    	if(this.tagName == null) {
    		return;
    	}
    	switch(this.tagName) {
    	case "name":
    		this.people.setName(value);
    		break;
    	case "password":
    		this.people.setPassword(value);
    		break;
    	}
    }
    
    @Override
    public void endElement(String uri, String localName, String qName)
                throws SAXException{
    	if(qName.equals("people")) {
    		this.userList.add(this.people);
    	}
    	//因为tagName要多次使用,当前结点结束后,要将tagName置空
    	this.tagName = null;
    }
}

其实一开始学SAX解析的时候有很多困惑,比如它的解析流程是怎样的。SAX解析是流解析,从头到尾扫描完,也就解析完了。所以除了startDocument()和endDocument()只会调用一次,其他的方法都会调用多次。

第四步:
新建一个工具类,用于获取解析后XMLParserHandler。

	public static XMLParserHandler getXMLParserHandler() {
		try {
			// 构建SAXParser
			SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
			// 实例化DefaultHandler对象
			XMLParserHandler xmlParserHandler = new XMLParserHandler();
			// 加载资源文件 转化为一个输入流
			InputStream inputStream = xmlParserHandler.getClass().
					getClassLoader().getResourceAsStream("people.xml");
			// 调用parse()方法
			parser.parse(inputStream, xmlParserHandler);
			//返回解析后的XMLParserHandler
			return xmlParserHandler;
		} catch (ParserConfigurationException | SAXException | IOException e) {
			e.printStackTrace();
		}
		return null;
	}

编写测试类:

	public static void main(String[] args) {
		XmlParseUtil xmlParseUtil = new XmlParseUtil();
		XMLParserHandler handler = xmlParseUtil.getXMLParserHandler();
		List<People> peopleList = handler.getUserList();
		for (People people : peopleList) {
			System.out.println(people);
		}
	}

结果:

People [id=1, name=李四, password=123456]
People [id=2, name=张三, password=174896]
People [id=3, name=王五, password=123]

最后再记录一下Web项目中,通用的获取XMLParserHandler的工具类:

    public static <T extends DefaultHandler> T getXmlResolveHelper(T handler, String path, ServletContext
            servletContext) {
        try {
            // 构建SAXParser
            SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
            // 加载资源文件 转化为一个输入流
            InputStream stream = servletContext.getResourceAsStream(path);
            // 调用parse()方法
            parser.parse(stream, handler);
            stream.close();
        } catch (ParserConfigurationException | SAXException | IOException e) {
            e.printStackTrace();
        }
        return handler;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值