加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

SAX解析多层嵌套XML

发布时间:2020-12-16 09:27:54 所属栏目:百科 来源:网络整理
导读:最近工程需要解析多层嵌套XML,没有找到合适的公共解析的,要是一个类自己对应写一个解析方法,岂不累死,于是自己写了个通用的解析类。现在还不是很完善,对子类的解析需要提前指定好子类不能动态解析。 我用的是DefaultHandler来处理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 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();

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读