最近工程需要解析多层嵌套XML,没有找到合适的公共解析的,要是一个类自己对应写一个解析方法,岂不累死,于是自己写了个通用的解析类。现在还不是很完善,对子类的解析需要提前指定好子类不能动态解析。
我用的是DefaultHandler来处理XML,里面方法执行过程是
public void startDocument() throws SAXException
第一个执行方法。
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
该方法是继第一个方法后第二个执行方法。
public void characters(char[] ch, int start, int length) throws SAXException
这个是继startElement方法后的执行方法。
该方法中的ch把所解析的xml的所有数据都保存进来,且ch初始化为2K数据。 start是一个节点">"的位置。length就是">"到下一个"<"的长度。
public void endElement(String uri, String localName, String qName) throws SAXException
若一个节点,比如<name>michael</name>,在执行完characters后会执行该方法。
如果节点,比如<names><name>michael</name></names>在执行names节点时,不会执行到该方法。
public void endDocument() throws SAXException
最后一个执行方法。
解析类如下:
import java.io.IOException;
import java.io.StringReader;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
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;
import com.app.dftr.tzsb.zf.model.WcfCity;
import com.app.dftr.tzsb.zf.model.WcfCounty;
import com.app.dftr.tzsb.zf.model.WcfRegion;
/**
*
* 类描述: XML解析类
*
* @author CHD
* @version
* @Date 日期 : 2014-11-7 时间 : 下午3:46:34
*/
public class SAXParseXMLTools<T> extends DefaultHandler {
private String TAG = SAXParseXMLTools.class.getSimpleName();
private String content; // 解析内容
private String objName; // obj名称
private Object obj; // obj
private Class<?> cla;
private ListSets<T> results = null;
private Field[] cla_fields; // obj的所有域
private Method[] cla_methods; // obj的方法
private String tag_name; // 当前标签
private String super_tag_name; // 父级标签
public ListSets<T> getResults() {
try {
XMLReader reader = null;
SAXParserFactory factory = SAXParserFactory.newInstance();
reader = factory.newSAXParser().getXMLReader();
reader.setContentHandler(this);
reader.parse(new InputSource(new StringReader(content)));
} catch (Exception e) {
// TODO: handle exception
DebugLog.printError(TAG, "解析出现异常" + e.getMessage());
}
return results;
}
public SAXParseXMLTools(String result, Class<?> clas, String objname) {
results = new ListSets<T>();
content = result;
cla = clas;
objName = objname;
try {
obj = cla.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
cla_fields = obj.getClass().getDeclaredFields();// 根据Class对象获取属性
cla_methods = obj.getClass().getDeclaredMethods();// 根据Class对象获取所有方法
}
@Override
public void startDocument() throws SAXException {
DebugLog.printInfor(TAG, "开始解析!");
super.startDocument();
}
@Override
public void endDocument() throws SAXException {
DebugLog.printInfor(TAG, "解析完成!");
super.endDocument();
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (qName.equals(objName)) {
try {
obj = cla.newInstance();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super_tag_name = qName;
} else {
tag_name = qName;
try {
Field field = obj.getClass().getDeclaredField(tag_name);
Class fieldClazz = field.getType(); // 得到field的class及类型全路径
if (fieldClazz.isPrimitive()) { // 【1】 判断是否为基本类型
}
if (fieldClazz.getName().startsWith("java.lang")) { // getName()返回field的类型全路径;
}
if (fieldClazz.isAssignableFrom(List.class)) // 【2】判断是否为队列
{
Type fc = field.getGenericType(); // 关键的地方,如果是List类型,得到其Generic的类型
if (null != fc) {
if (fc instanceof ParameterizedType) // 【3】如果是泛型参数的类型
{
ParameterizedType pt = (ParameterizedType) fc;
Class genericClazz = (Class) pt
.getActualTypeArguments()[0]; // 【4】得到泛型里的class类型对象。
String regex = "<" + tag_name + ">(.*?)</"
+ tag_name + ">";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
String tempStr = matcher.group();
results.setNextStr(tempStr); // 队列的字符串
matcher.replaceFirst("");
if(tag_name.equals("City")) { // 城市
SAXParseXMLTools<WcfCity> appointHanlder = new SAXParseXMLTools<WcfCity>(
tempStr, genericClazz,
genericClazz.getSimpleName());
ListSets<WcfCity> results = appointHanlder
.getResults();
try {
Class[] args1 = new Class[1];
args1[0] = List.class;
Method tempMethod = obj.getClass().getDeclaredMethod("set" + tag_name, args1);
tempMethod.invoke(obj, results.getResultSet());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else if(tag_name.equals("County")) { // 县城
SAXParseXMLTools<WcfCounty> appointHanlder = new SAXParseXMLTools<WcfCounty>(
tempStr, genericClazz,
genericClazz.getSimpleName());
ListSets<WcfCounty> results = appointHanlder
.getResults();
try {
Class[] args1 = new Class[1];
args1[0] = List.class;
Method tempMethod = obj.getClass().getDeclaredMethod("set" + tag_name, args1);
tempMethod.invoke(obj, results.getResultSet());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else if(tag_name.equals("Region")) { // 区域
SAXParseXMLTools<WcfRegion> appointHanlder = new SAXParseXMLTools<WcfRegion>(
tempStr, genericClazz,
genericClazz.getSimpleName());
ListSets<WcfRegion> results = appointHanlder
.getResults();
try {
Class[] args1 = new Class[1];
args1[0] = List.class;
Method tempMethod = obj.getClass().getDeclaredMethod("set" + tag_name, args1);
tempMethod.invoke(obj, results.getResultSet());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
super.startElement(uri, localName, qName, attributes);
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (qName.equals(super_tag_name)) {
results.getResultSet().add((T) obj);
}
super.endElement(uri, localName, qName);
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
String temp = new String(ch, start, length);
if (tag_name.equals("_WcfReturnState") && (0 == results.getResult())) {// 解析头部
results.setResult(Integer.parseInt(temp));
} else if (tag_name.equals("_WcfReturnMessage")) {
results.setMessage(temp);
}
if (null != super_tag_name && super_tag_name.equals(objName)) {// 确保在父类下
for (Field cla_f : cla_fields) {
if (cla_f.getName().equals(tag_name)) {
String value = new String(ch, start, length);
for (Method cla_method : cla_methods) {
String meth = cla_method.getName();
// 匹配set方法
if (meth != null
&& "set".equals(meth.substring(0, 3))
&& Modifier.isPublic(cla_method.getModifiers())
&& ("set"
+ Character.toUpperCase(cla_f.getName()
.charAt(0)) + cla_f.getName()
.substring(1)).equals(meth)) {
// 调用set方法并赋值
try {
cla_method.invoke(obj, value);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
}
super.characters(ch, start, length);
}
}前端获取list很简洁,两行就ok,
SAXParseXMLTools<WcfEnterprise> appointHanlder = new SAXParseXMLTools<WcfEnterprise>(result, WcfEnterprise.class, WcfEnterprise.class.getSimpleName()); ListSets<WcfEnterprise> results = appointHanlder.getResults();
原文地址:http://blog.csdn.net/tz2101/article/details/40893959