package SAXparse;
import java.io.FileInputStream;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import javax.sql.rowset.spi.XmlReader;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.w3c.dom.Element;
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 SaxParse {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
SAXParserFactory saxpf = SAXParserFactory.newInstance();
SAXParser saxp = saxpf.newSAXParser();
XMLReader reader = saxp.getXMLReader();
//这里不同于DOM解析式多了一个Handler 创建一个将要解析文件的Handler类继承 DefaultHandler
EmployeeHandler empHander = new EmployeeHandler();
reader.setContentHandler(empHander);
//set Handler
reader.parse(new InputSource(new FileInputStream("file/xml/employeelist.xml")));
//开始解析,SAX 开始解析的时候 就会自动调用 EmployeeHandler 中的方法 开始解析调用startDocument(),开始解析一个元素调用startElement()。
ArrayList empList = empHander.getEmployeeList();
for(Employee emp:empList){
System.out.println(emp);
}
}
}
class EmployeeHandler extends DefaultHandler{
//EmployeeHandler 继承DefaultHandler 然后根据需要选择要重载的 方法
//这里我重载了 startDocument endDocument startElement endElement endElement characters
private ArrayList employeeList = new ArrayList();
//创建一个list 来保存解析出来的employee对象
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
System.out.println("begin");
//开始解析 打印 begin
}
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
System.out.println("end");
//结束后打印end
}
private Employee emp =null;
private Class cls =null;
private String qName=null;
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
this.qName =qName;
//在这里保存一下 元素的名称,在characters()有用到
try {
cls =Class.forName("SAXparse.Employee");
//反射机制
Method[] methods =cls.getMethods();
if(qName.equals("employee")||qName.equals("salary")){
//如果qName=employee 也就是解析到了 employee元素和salary 元素才继续
//因为employee就是要建立的对象,每当解析到一个employee元素就创建一个employee对象
//salary 因为有属性所以也单独拿出来
if(emp==null){
//如果employee对象不存在 就创建
emp = (Employee) cls.newInstance();
System.out.println("创建一个emp对象");
}
for(Method me : methods){
String meName = me.getName();
if(meName.startsWith("set")){
String mName = meName.substring(3).toLowerCase();
Class[] parm = me.getParameterTypes();
String parma = parm[0].getName();
for(int i=0;i
String attrName = attributes.getQName(i);
//直接从函数参数中拿到attributes 这里也就是 SAX我感觉 比DOM 效率高的地方
//是顺序解析的。但是自由度就没有DOM解析高了
String attrVal = attributes.getValue(i);
if(mName.equals(attrName.toLowerCase())){
if(parma.equals("java.lang.String")){
//吧属性set进emp对象中
me.invoke(emp,attrVal );
}
}
}
}
}
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if(qName.equals("employee")){
employeeList.add(emp);
System.out.println("加入一个emp");
emp=null;
//判断 是不是在employee元素结束的,是的话证明 一个employee对象已经解析完成
//这样子的话就加入list中 保险起见 清空emp
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
String text =new String(ch,start,length);
//text是指SAX解析到的所有文本节点,包括 空格。所以要去掉空格,判断是否为空
if(!text.trim().equals("")){
//text是指SAX解析到的所有文本节点,包括 空格。所以要去掉空格,判断是否为空,为空TEXT就不是要加入的字符串信息
Method[] methods = cls.getMethods();
//反射机制
for(Method me:methods){
String meName = me.getName();
if( meName.startsWith("set")){
String mName = meName.substring(3).toLowerCase();
Class[] parm = me.getParameterTypes();
String parma = parm[0].getName();
if(qName.toLowerCase().equals(mName)){
//拿到刚刚保存的qName 比较方法名,判断使用什么样的SET方法。不这样的话 是没有办法比较方法名的。这也是为什么要从startElement方法中 保存qName的原因
try {
//把各个属性set进emp中
if(parma.equals("java.lang.String")){
me.invoke(emp, text);
}else if(parma.equals("java.lang.Double")){
me.invoke(emp, Double.parseDouble(text));
}else if (parma.equals("java.util.Date")){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
me.invoke(emp, sdf.parse(text));
}
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
public ArrayList getEmployeeList() {
return employeeList;
}
}