首页 > 代码库 > SAX解析多层嵌套XML
SAX解析多层嵌套XML
最近工程需要解析多层嵌套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 = http://www.mamicode.com/new String(ch, start, length);>
注释写的很详细。前端获取list很简洁,两行就ok,
SAXParseXMLTools<WcfEnterprise> appointHanlder = new SAXParseXMLTools<WcfEnterprise>(result, WcfEnterprise.class, WcfEnterprise.class.getSimpleName()); ListSets<WcfEnterprise> results = appointHanlder.getResults();
SAX解析多层嵌套XML