前面说到了pull解析和dom解析、自然少不了sax解析、而在这里、我将sax解析写成接口、方便更具扩展性、
比如要处理类似格式的xml文件:
<?xml version="1.0" encoding="utf-8"?>
<!-- 结果信息 -->
<result>
<resultCode>1</resultCode>
<resultMessage>结果信息</resultMessage>
</result>
<!-- 下面是xml数据 -->
结果信息实体类:
public class ResultInfo {
private String resultCode;
private String resultMessage="";
public static final String RESULT_CODE_OK = "1";
public static final String RESULT_CODE_ERROR = "0";
//-------------------------------
public ResultInfo(){
}
public ResultInfo(String resultCode,String resultMessage){
this.resultCode = resultCode;
this.resultMessage = resultMessage;
}
//-------------------------------
public String getResultCode() {
return resultCode;
}
public void setResultCode(String resultCode) {
this.resultCode = resultCode;
}
public String getResultMessage() {
return resultMessage;
}
public void setResultMessage(String resultMessage) {
this.resultMessage = resultMessage;
}
//-------------------------------
@Override
public String toString() {
return "resultInfo:["+resultCode+" "+resultMessage +"]";
}
上面的resultCode也可以直接写成int类型的、只不过在下面需要转换下、
public abstract class AbstractHandler extends DefaultHandler{
protected final String CLAZZ = "AbstractHandler";
//-----------------------------------------
public static final String TAG_NAME_RESULT_INFO = "result";
public static final String TAG_NAME_RESULT_CODE = "resultCode";
public static final String TAG_NAME_RESULT_MESSAGE = "resultMessage";
//-----------------------------------------
private String tagName;
private String content;
private ResultInfo resultInfo;
//-----------------------------------------
public String getTagName() {
return tagName;
}
public void setTagName(String tagName) {
this.tagName = tagName;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public ResultInfo getResultInfo() {
return resultInfo;
}
public void setResultInfo(ResultInfo resultInfo) {
this.resultInfo = resultInfo;
}
//-----------------------------------------
@Override
public void startDocument() throws SAXException {
super.startDocument();
}
//-----------------------------------------
@Override
public void endDocument() throws SAXException {
super.endDocument();
}
//-----------------------------------------
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
this.tagName = localName;
if(TAG_NAME_RESULT_INFO.equalsIgnoreCase(localName)){
resultInfo = new ResultInfo();
}else if(TAG_NAME_PAGE_INFO.equalsIgnoreCase(localName)){
pageInfo = new PageInfo();
}else{
startElements(uri, localName, qName, attributes);
}
}
//-----------------------------------------
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
content = new String(ch,start,length);
try{
if(!TextUtils.isEmpty(content.trim())){
if(TAG_NAME_RESULT_CODE.equalsIgnoreCase(tagName)){
resultInfo.setResultCode(content);
}else if(TAG_NAME_RESULT_MESSAGE.equalsIgnoreCase(tagName)){
resultInfo.setResultMessage(content);
}else{
characterss(ch, start, length);
}
}
LogUtils.logI(tagName+"\t-------\t"+content);
}catch (NumberFormatException e) {
LogUtils.logE(CLAZZ, "数字格式化错误!");
}catch (Exception e) {
LogUtils.logE(CLAZZ, e.getMessage());
e.printStackTrace();
}
}
//-----------------------------------------
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
endElements(uri, localName, qName);
}
//-----------------------------------------
public abstract void startElements(String uri, String localName, String qName, Attributes attributes);
public abstract void characterss(char[] ch, int start, int length);
public abstract void endElements(String uri,String localName,String qName);
}
在这里之所以将AbstractHandler写成抽象类、就是为了更具有扩展性的去处理上面的xml标记的<!-- 下面是xml数据 -->这些可扩展的未知数据、
接着写个默认的ResultHandler继承AbstractHandler去实现抽象方法:
public class ResultHandler extends AbstractHandler{
@Override
public void startElements(String uri, String localName, String qName, Attributes attributes) {
}
@Override
public void characterss(char[] ch, int start, int length) {
}
@Override
public void endElements(String uri, String localName, String qName) {
}
}
以上只是针对于上面风格的xml文件写了个处理器Handler、接着下面还需通过SAXParserFactory得到一个XMLReader、不过在这里、得先写个XmlParser接口
XmlParser接口:
public interface XmlParser {
/**
* XML解析回调接口
*/
public interface XmlParserCallback{
void onFinish();
void onError(String error);
}
public void parse(InputSource inputSource);
public void parse(String response);
}
然后写个XmlParserImpl实现XmlParser接口:
public class XmlParserImpl implements XmlParser{
//-----------------------------------------
private AbstractHandler handler;
private XmlParserCallback callback;
//-----------------------------------------
public XmlParserImpl(AbstractHandler handler,XmlParserCallback callback){
if(null!=handler){
this.handler = handler;
}else{
this.handler = new ResultHandler();
}
this.callback = callback;
}
//-----------------------------------------
@Override
public void parse(String response){
parse(new InputSource(new StringReader(response)));
}
@Override
public void parse(InputSource inputSource) {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
XMLReader xmlReader = factory.newSAXParser().getXMLReader();
xmlReader.setContentHandler(handler);
xmlReader.parse(inputSource);
ResultInfo resultInfo = handler.getResultInfo();
if(ResultInfo.RESULT_CODE_OK.equals(resultInfo.getResultCode())){
callback.onFinish();
}else{
callback.onError("解析结果码:"+resultInfo.getResultCode()+"\n结果信息:"+resultInfo.getResultMessage());
}
}catch(Exception e){
callback.onError("XML解析出错!");
e.printStackTrace();
}
}
}
这样、其实一个可扩展性的sax解析就完成了、只要直接new一个XmlParserImpl就可以直接解析了、比如就解析那个默认的xml文件:
final ResultHandler resultHandler = new ResultHandler();
XmlParser xmlParser = new XmlParserImpl(resultHandler , new XmlParserCallback() {
@Override
public void onFinish() {
//表示成功、结果码为1
System.out.println(resultHandler.getResultInfo().toString());//结果信息
}
@Override
public void onError(String error) {
}
});
xmlParser.parse(xml);//xml以InputStream或String都行
若需扩展只要写个类去实现AbstractHandler、根据节点来解析扩展的数据即可、
ps:像这样半封装式的写个sax解析接口并实现它、总结一些共性的是不是很好呢、