最近工程需要解析多层嵌套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 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(); <span style="white-space:pre"> </span>private String content;<span style="white-space:pre"> </span>// 解析内容 <span style="white-space:pre"> </span>private String objName;<span style="white-space:pre"> </span>// obj名称 <span style="white-space:pre"> </span>private Object obj;<span style="white-space:pre"> </span>// obj <span style="white-space:pre"> </span>private Class<?> cla; <span style="white-space:pre"> </span>private ListSets<T> results = null; <span style="white-space:pre"> </span>private Field[] cla_fields;<span style="white-space:pre"> </span>// obj的所有域 <span style="white-space:pre"> </span>private Method[] cla_methods;<span style="white-space:pre"> </span>// obj的方法 <span style="white-space:pre"> </span>private String tag_name;<span style="white-space:pre"> </span>// 当前标签 <span style="white-space:pre"> </span>private String super_tag_name;<span style="white-space:pre"> </span>// 父级标签 <span style="white-space:pre"> </span>public ListSets<T> getResults() { <span style="white-space:pre"> </span>try { <span style="white-space:pre"> </span>XMLReader reader = null; <span style="white-space:pre"> </span>SAXParserFactory factory = SAXParserFactory.newInstance(); <span style="white-space:pre"> </span>reader = factory.newSAXParser().getXMLReader(); <span style="white-space:pre"> </span>reader.setContentHandler(this); <span style="white-space:pre"> </span>reader.parse(new InputSource(new StringReader(content))); <span style="white-space:pre"> </span>} catch (Exception e) { <span style="white-space:pre"> </span>// TODO: handle exception <span style="white-space:pre"> </span>DebugLog.printError(TAG,"解析出现异常" + e.getMessage()); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>return results; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public SAXParseXMLTools(String result,Class<?> clas,String objname) { <span style="white-space:pre"> </span>results = new ListSets<T>(); <span style="white-space:pre"> </span>content = result; <span style="white-space:pre"> </span>cla = clas; <span style="white-space:pre"> </span>objName = objname; <span style="white-space:pre"> </span>try { <span style="white-space:pre"> </span>obj = cla.newInstance(); <span style="white-space:pre"> </span>} catch (InstantiationException e) { <span style="white-space:pre"> </span>// TODO Auto-generated catch block <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>} catch (IllegalAccessException e) { <span style="white-space:pre"> </span>// TODO Auto-generated catch block <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>cla_fields = obj.getClass().getDeclaredFields();// 根据Class对象获取属性 <span style="white-space:pre"> </span>cla_methods = obj.getClass().getDeclaredMethods();// 根据Class对象获取所有方法 <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>@Override <span style="white-space:pre"> </span>public void startDocument() throws SAXException { <span style="white-space:pre"> </span>DebugLog.printInfor(TAG,"开始解析!"); <span style="white-space:pre"> </span>super.startDocument(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>@Override <span style="white-space:pre"> </span>public void endDocument() throws SAXException { <span style="white-space:pre"> </span>DebugLog.printInfor(TAG,"解析完成!"); <span style="white-space:pre"> </span>super.endDocument(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>@Override <span style="white-space:pre"> </span>public void startElement(String uri,<span style="white-space:pre"> </span>Attributes attributes) throws SAXException { <span style="white-space:pre"> </span>if (qName.equals(objName)) { <span style="white-space:pre"> </span>try { <span style="white-space:pre"> </span>obj = cla.newInstance(); <span style="white-space:pre"> </span>} catch (InstantiationException e) { <span style="white-space:pre"> </span>// TODO Auto-generated catch block <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>} catch (IllegalAccessException e) { <span style="white-space:pre"> </span>// TODO Auto-generated catch block <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>super_tag_name = qName; <span style="white-space:pre"> </span>} else { <span style="white-space:pre"> </span>tag_name = qName; <span style="white-space:pre"> </span>try { <span style="white-space:pre"> </span>Field field = obj.getClass().getDeclaredField(tag_name); <span style="white-space:pre"> </span>Class fieldClazz = field.getType(); // 得到field的class及类型全路径 <span style="white-space:pre"> </span>if (fieldClazz.isPrimitive()) { // 【1】 判断是否为基本类型 <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>if (fieldClazz.getName().startsWith("java.lang")) { // getName()返回field的类型全路径; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>if (fieldClazz.isAssignableFrom(List.class)) // 【2】判断是否为队列 <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>Type fc = field.getGenericType(); // 关键的地方,如果是List类型,得到其Generic的类型 <span style="white-space:pre"> </span>if (null != fc) { <span style="white-space:pre"> </span>if (fc instanceof ParameterizedType) // 【3】如果是泛型参数的类型 <span style="white-space:pre"> </span>{ <span style="white-space:pre"> </span>ParameterizedType pt = (ParameterizedType) fc; <span style="white-space:pre"> </span>Class genericClazz = (Class) pt <span style="white-space:pre"> </span>.getActualTypeArguments()[0]; // 【4】得到泛型里的class类型对象。 <span style="white-space:pre"> </span>String regex = "<" + tag_name + ">(.*?)</" <span style="white-space:pre"> </span>+ tag_name + ">"; <span style="white-space:pre"> </span>Pattern pattern = Pattern.compile(regex); <span style="white-space:pre"> </span>Matcher matcher = pattern.matcher(content); <span style="white-space:pre"> </span>if(matcher.find()) { <span style="white-space:pre"> </span>String tempStr = matcher.group(); <span style="white-space:pre"> </span>results.setNextStr(tempStr); // 队列的字符串 <span style="white-space:pre"> </span>content = matcher.replaceFirst(""); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>if(tag_name.equals("City")) {<span style="white-space:pre"> </span>// 城市 <span style="white-space:pre"> </span>SAXParseXMLTools<WcfCity> appointHanlder = new SAXParseXMLTools<WcfCity>( <span style="white-space:pre"> </span>tempStr,genericClazz,<span style="white-space:pre"> </span>genericClazz.getSimpleName()); <span style="white-space:pre"> </span>ListSets<WcfCity> results = appointHanlder <span style="white-space:pre"> </span>.getResults(); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>try { <span style="white-space:pre"> </span>Class[] args1 = new Class[1]; <span style="white-space:pre"> </span>args1[0] = List.class; <span style="white-space:pre"> </span>Method tempMethod = obj.getClass().getDeclaredMethod("set" + tag_name,args1); <span style="white-space:pre"> </span>tempMethod.invoke(obj,results.getResultSet()); <span style="white-space:pre"> </span>} catch (Exception e) { <span style="white-space:pre"> </span>// TODO Auto-generated catch block <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} else if(tag_name.equals("County")) { // 县城 <span style="white-space:pre"> </span>SAXParseXMLTools<WcfCounty> appointHanlder = new SAXParseXMLTools<WcfCounty>( <span style="white-space:pre"> </span>tempStr,<span style="white-space:pre"> </span>genericClazz.getSimpleName()); <span style="white-space:pre"> </span>ListSets<WcfCounty> results = appointHanlder <span style="white-space:pre"> </span>.getResults(); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>try { <span style="white-space:pre"> </span>Class[] args1 = new Class[1]; <span style="white-space:pre"> </span>args1[0] = List.class; <span style="white-space:pre"> </span>Method tempMethod = obj.getClass().getDeclaredMethod("set" + tag_name,results.getResultSet()); <span style="white-space:pre"> </span>} catch (Exception e) { <span style="white-space:pre"> </span>// TODO Auto-generated catch block <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} else if(tag_name.equals("Region")) { // 区域 <span style="white-space:pre"> </span>SAXParseXMLTools<WcfRegion> appointHanlder = new SAXParseXMLTools<WcfRegion>( <span style="white-space:pre"> </span>tempStr,<span style="white-space:pre"> </span>genericClazz.getSimpleName()); <span style="white-space:pre"> </span>ListSets<WcfRegion> results = appointHanlder <span style="white-space:pre"> </span>.getResults(); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>try { <span style="white-space:pre"> </span>Class[] args1 = new Class[1]; <span style="white-space:pre"> </span>args1[0] = List.class; <span style="white-space:pre"> </span>Method tempMethod = obj.getClass().getDeclaredMethod("set" + tag_name,results.getResultSet()); <span style="white-space:pre"> </span>} catch (Exception e) { <span style="white-space:pre"> </span>// TODO Auto-generated catch block <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} else if(tag_name.equals("SecondDeviceType")) { // 区域 <span style="white-space:pre"> </span>SAXParseXMLTools<WcfSecondDeviceType> appointHanlder = new SAXParseXMLTools<WcfSecondDeviceType>( <span style="white-space:pre"> </span>tempStr,<span style="white-space:pre"> </span>genericClazz.getSimpleName()); <span style="white-space:pre"> </span>ListSets<WcfSecondDeviceType> results = appointHanlder <span style="white-space:pre"> </span>.getResults(); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>try { <span style="white-space:pre"> </span>Class[] args1 = new Class[1]; <span style="white-space:pre"> </span>args1[0] = List.class; <span style="white-space:pre"> </span>Method tempMethod = obj.getClass().getDeclaredMethod("set" + tag_name,results.getResultSet()); <span style="white-space:pre"> </span>} catch (Exception e) { <span style="white-space:pre"> </span>// TODO Auto-generated catch block <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} catch (NoSuchFieldException e) { <span style="white-space:pre"> </span>// TODO Auto-generated catch block <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>super.startElement(uri,localName,qName,attributes); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>@Override <span style="white-space:pre"> </span>public void endElement(String uri,String qName) <span style="white-space:pre"> </span>throws SAXException { <span style="white-space:pre"> </span>if (qName.equals(super_tag_name)) { <span style="white-space:pre"> </span>results.getResultSet().add((T) obj); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>super.endElement(uri,qName); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>@Override <span style="white-space:pre"> </span>public void characters(char[] ch,int length) <span style="white-space:pre"> </span>throws SAXException { <span style="white-space:pre"> </span>String temp = new String(ch,start,length); <span style="white-space:pre"> </span>if (tag_name.equals("_WcfReturnState") && (0 == results.getResult())) {// 解析头部 <span style="white-space:pre"> </span>results.setResult(Integer.parseInt(temp)); <span style="white-space:pre"> </span>} else if (tag_name.equals("_WcfReturnMessage")) { <span style="white-space:pre"> </span>results.setMessage(temp); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>if (null != super_tag_name && super_tag_name.equals(objName)) {// 确保在父类下 <span style="white-space:pre"> </span>for (Field cla_f : cla_fields) { <span style="white-space:pre"> </span>if (cla_f.getName().equals(tag_name)) { <span style="white-space:pre"> </span>String value = new String(ch,length); <span style="white-space:pre"> </span>for (Method cla_method : cla_methods) { <span style="white-space:pre"> </span>String meth = cla_method.getName(); <span style="white-space:pre"> </span>// 匹配set方法 <span style="white-space:pre"> </span>if (meth != null <span style="white-space:pre"> </span>&& "set".equals(meth.substring(0,3)) <span style="white-space:pre"> </span>&& Modifier.isPublic(cla_method.getModifiers()) <span style="white-space:pre"> </span>&& ("set" <span style="white-space:pre"> </span>+ Character.toUpperCase(cla_f.getName() <span style="white-space:pre"> </span>.charAt(0)) + cla_f.getName() <span style="white-space:pre"> </span>.substring(1)).equals(meth)) { <span style="white-space:pre"> </span>// 调用set方法并赋值 <span style="white-space:pre"> </span>try { <span style="white-space:pre"> </span>cla_method.invoke(obj,value); <span style="white-space:pre"> </span>} catch (IllegalArgumentException e) { <span style="white-space:pre"> </span>// TODO Auto-generated catch block <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>} catch (IllegalAccessException e) { <span style="white-space:pre"> </span>// TODO Auto-generated catch block <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>} catch (InvocationTargetException e) { <span style="white-space:pre"> </span>// TODO Auto-generated catch block <span style="white-space:pre"> </span>e.printStackTrace(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>super.characters(ch,length); <span style="white-space:pre"> </span>} }
注释写的很详细。
前端获取list很简洁,两行就ok,
SAXParseXMLTools<WcfEnterprise> appointHanlder = new SAXParseXMLTools<WcfEnterprise>(result,WcfEnterprise.class,WcfEnterprise.class.getSimpleName()); ListSets<WcfEnterprise> results = appointHanlder.getResults();原文链接:https://www.f2er.com/xml/297742.html