如何使用sax解析xml文档


  对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;
}

	@Override
	public void startDocument() throws SAXException {
		// TODO Auto-generated method stub
		super.startDocument();
		Log.v(TAG, "$$$$$-----startDocument----$$$$");
		students = new ArrayList<student>();// 适合在此事件中触发初始化行为
	}
	

	@Override
	public 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));//获取第一个属性并设置id
			Log.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);
		}
	}
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		// TODO Auto-generated method stub
		super.endElement(uri, localName, qName);
		Log.v(TAG, "$$$$$-----endElement----$$$$");
		if (localName.equals("student")) {//结束标签student
			students.add(s);//把一个解析好的对象加入集合中,在进行下一个解析,并将student对象与自定义标签赋值为空
			s=null;		
		}
		sName=null;
	}

	@Override
	public void endDocument() throws SAXException {
		// TODO Auto-generated method stub
		super.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();
	}
	@Override
	public 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Java中使用SAX解析XML,你可以按照以下步骤进行操作: 1. 导入相关的类和包,如`javax.xml.parsers.SAXParser`和`javax.xml.parsers.SAXParserFactory`。 2. 创建`SAXParserFactory`的实例。 3. 通过调用`SAXParserFactory`的`newSAXParser()`方法创建一个解析器。 4. 获取需要解析XML文档,并创建一个`File`对象来表示该文档。 5. 创建一个自定义的`SAXHandler`类,该类继承自`DefaultHandler`类,并重写需要的回调方法来处理XML元素和数据。 6. 调用解析器的`parse()`方法,传入文件和自定义的`SAXHandler`对象作为参数,开始解析XML文档。 你可以参考以下示例代码: ```java import java.io.File; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; public class TestDemo { public static void main(String[] args) throws Exception { // 1.实例化SAXParserFactory对象 SAXParserFactory factory = SAXParserFactory.newInstance(); // 2.创建解析SAXParser parser = factory.newSAXParser(); // 3.获取需要解析文档,生成解析器,最后解析文档 File f = new File("books.xml"); SaxHandler dh = new SaxHandler(); parser.parse(f, dh); } } ``` 请注意,上述代码中的`SaxHandler`是一个自定义的类,你需要根据自己的需求来实现该类,以便在解析XML时处理相应的元素和数据。 XML文档如下所示: ```xml <?xml version="1.0" encoding="UTF-8"?> <books> <book id="001"> <title>Harry Potter</title> <author>J K. Rowling</author> </book> <book id="002"> <title>Learning XML</title> <author>Erik T. Ray</author> </book> </books> ``` 希望以上信息能够帮到你。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [java中使用sax解析xml的解决方法](https://download.csdn.net/download/weixin_38747216/12815749)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [在java中使用sax解析xml](https://blog.csdn.net/weixin_33884611/article/details/86303531)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值