android 自带sax解析

public class AtomParser extends DefaultHandler {
// br节点高度,如果有连续的br节点,则存在br节点高度值,且该值项目组可通过brHeight配置具体大小
private int brHeight_;
// 判断br节点是否连续
private int brIndex_;
// 脚本文件,该内容应该在解析完页面后执行,
private Stack scriptStack_;
// 节点样式display属性列表,存储每个节点样式display的属性值。由于在节点尾需要读取对应的display属性,所以创建该堆栈
private Stack displayStack_;
// 标志控件在Br节点之后
static boolean ISAFTERBR;
// 是否已插入界面中部结构
boolean isInsertLLV_;
Activity activity_;
// 节点队列,方便添加子节点
Stack stack_;
// 节点名堆栈
Stack nodeNameStack_;
final int START_DOCUMENT = 0;
final int END_DOCUMENT = 1;
final int START_TAG = 2;
final int END_TAG = 3;
final int TEXT = 4;
// 触发的事件类型
int eventType_;
// 读取中间节点值的次数
int readTextIndex_;
// 存储节点值
StringBuffer buf_ = new StringBuffer(10);
private LPPieChart pieChart_;
private LPSelect select_;
// 解析类型,是全部解析或者局部解析
private int parseType_;
// 解析出来是整个界面结构标志
public static final int ENTIRE = 0;
// 解析出来是局部控件标志
public static final int PARTLY = 1;
// 存储整个界面的样式,且里面内容只为当前界面样式一个元素,该界面指整个手机界面
// 并非弹出框的显示的部分界面,与PARTLY相对应
private static Stack ENTIRESTACK;
// 报文是否含样式节点标记
private boolean haveStyle_;


/**
*
* @param activity
* @param type
* 解析类型 0 整个界面结构解析 1 局部控件解析
*/
public AtomParser(Activity activity, int type) {
activity_ = activity;
parseType_ = type;
}


// XML开始解析时调用此方法
public void startDocument() throws SAXException {
eventType_ = START_DOCUMENT;
stack_ = new Stack();
nodeNameStack_ = new Stack();
displayStack_ = new Stack();
scriptStack_ = new Stack();
if (parseType_ == ENTIRE) {
Component.VWIDGETARRAY = new ArrayList(2);
ENTIRESTACK = new Stack();
Component.radioList_ = null;
}
ComponentCopy.CC = null;
}


// 解析到Element的开头时调用此方法
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
eventType_ = START_TAG;
// 将读取节点值次数标记复位
readTextIndex_ = 0;
nodeNameStack_.add(localName);
if (localName.equalsIgnoreCase("script")) {
Component.LUASTATE.gc(LuaState.LUA_GCCOLLECT, 0);
String src = getAttrString(atts, "src");
if (null != src) {
if (src.startsWith("/")) {
downloadLuaFromServer(src);
} else {
Component.LUASTATE.LdoString(Utils.getStringFormAsset(activity_, src));
}
}
} else if (((nodeNameStack_.indexOf("body") != -1) && (parseType_ == ENTIRE)) || (parseType_ == PARTLY)) {
if (localName.equalsIgnoreCase("style") || localName.equalsIgnoreCase("head")
|| localName.equalsIgnoreCase("content"))
return;
ComponentCopy ccCopy = new ComponentCopy();
ccCopy.setName(localName);
final int size = atts.getLength();
for (int i = 0; i < size; i++) {
// 循环读取节点中的属性,存入结构
ccCopy.addAttrs(atts.getLocalName(i), Utils.insteadOfSpecillCharacter(atts.getValue(i).trim(), false));
}


if (!stack_.isEmpty()) {
String temp = null;
if (null != ccCopy.nodeAttrsMap_ && !ccCopy.nodeAttrsMap_.isEmpty()) {
// 取当前节点的属性值,如果存在的话
temp = (String) ccCopy.nodeAttrsMap_.get("class");
}
if (null != temp && null != CssStyle.STYLEHASH) {
CssStyle cs = (CssStyle) CssStyle.STYLEHASH.get(temp.trim());
if (isInsertLLV_ && null != cs && null != cs.position_) {
// 如果已经插入llv节点,且当前节点存在positon属性,表示该节点占据的应是界面下方位置
// ,所以它不应该在llv节点内,此时应将llv节点从栈中移除。
// 暂时只支持上中下三结构的position的定位
stack_.pop();
}
}
}


String className = atts.getValue("class");
String display = null;
if (null != className) {
if (null != CssStyle.STYLEHASH) {
CssStyle cs = (CssStyle) CssStyle.STYLEHASH.get(className.trim());
if (null != cs) {
display = (String) cs.getProperty(CssStyle.DISPLAY);
}
}
}
displayStack_.add(display);
if (!localName.equalsIgnoreCase("body") && (!stack_.isEmpty())) {
// 此节点不是第一个节点,将该节点加入前面节点的子元素队列
((ComponentCopy) stack_.peek()).addChilds(ccCopy);
}
stack_.add(ccCopy);


}


}


/**
* 根据src中的url去服务器download指定的lua代码并加载到lua引擎中
*
* @param src
* eg: "/ebank/lua/ebank_request.lua"
*/
private void downloadLuaFromServer(String src) {
final String uri = Utils.getConfigStringFormAsset(activity_, "SERVER_URI").concat(src);
Utils.printOutToConsole("downloadLuaFromServer()------" + uri);
HttpManager hm = new HttpManager(activity_);
String luastr = (String) hm.sendPostRequest(uri, null, null, null);
if (luastr != null && !luastr.trim().equals("")) {
// 不要太频繁调gc.
// Component.LUASTATE.gc(LuaState.LUA_GCCOLLECT, 0);
Component.LUASTATE.LdoString(luastr);
}
}


// XML解析结束时调用此方法
public void endDocument() throws SAXException {
eventType_ = END_DOCUMENT;
activity_.runOnUiThread(new Runnable() {


@Override
public void run() {
// TODO Auto-generated method stub
// 当xml元素转为view的时候,防止view在创建过程中其他线程对view进行操作导致的异常
if (null != ComponentCopy.CC) {
xmlToView(ComponentCopy.CC, null);
if (parseType_ == ENTIRE) {
ComponentCopy.COMPONENT.mouldAndLayout();
} else {
ComponentCopy.COMPONENTPARTLY.mouldAndLayout();
}
}
if (null != scriptStack_ && scriptStack_.size() > 0) {
final int size = scriptStack_.size();
String scriptText = "";
int index;
synchronized (this) {
for (int i = 0; i < size; i++) {
scriptText = scriptStack_.get(i).toString();
index = Component.LUASTATE.LdoString(scriptText);


if (index > 0) {
Utils.printOutToConsole("Lua Text has some errors:");
Utils.printOutToConsole(Component.LUASTATE.LcheckString(-1));
}
}
}
}
// 清空该类用到的相关资源
stack_ = null;
nodeNameStack_ = null;
displayStack_ = null;
pieChart_ = null;
select_ = null;
activity_ = null;
buf_ = null;
if (null != scriptStack_)
scriptStack_.removeAllElements();
scriptStack_ = null;


}
});


}


/**
* 该方法将控件从树状结构ComponentCopy中解析出来,并将他们逐个加到上一级的childrenList_队列中
*
* @param cc
* 为控件自己
* @param component
* 为控件父控件
*/
private void xmlToView(ComponentCopy cc, Component component) {
// TODO Auto-generated method stub
try {
// 遍历cc中的所有元素,如果是样式报文,则将样式报文分解成样式序列
final String name = cc.nodeName_;
String nameType = (String) cc.getAttr("type");
if (null == nameType)
nameType = "";
// 如果cc是其他元素则查看它是不是控件
// 先将cc在控件列表ParseWidgets.WIDGETSLIST中对应的控件查找出来


Object o = ParseWidgets.initWidget(cc.nodeName_.concat("-").concat(nameType));
if (o instanceof LPWrap) {
ISAFTERBR = true;
brIndex_++;
// br节点连续,则需要计算控件前面br的累加高度和框架内控件间距,
// br高度值在Config配置文件中通过brHeight设置
if (brIndex_ > 1) {
int h = 0;
if (component instanceof LPLayout)
h = ((LPLayout) component).getVG();
brHeight_ += Utils.getBrHeight() + h;
}
return;
} else {
brIndex_ = 0;
}


if (null != o) {
Component comp = (Component) o;
// 如果元素o不为空,说明是系统控件此时要做以下几点事情:
// 1、将对应的cssstyle样式赋给该控件
// 如果当前报文没有style样式节点,且解析类型为局部解析
// 表示当前报文做的操作为局部刷新,控件样式需要对应到最近的全局报文中去
if (!haveStyle_ && parseType_ == PARTLY && null != ENTIRESTACK && !ENTIRESTACK.isEmpty())
CssStyle.STYLEHASH = (HashMap) ENTIRESTACK.get(0);
comp.setCssStyle((CssStyle) CssStyle.STYLEHASH.get(cc.nodeAttrsMap_.get("class")));
// 2、将对应的属性集合赋给该控件
comp.setProperty((HashMap) cc.getAttrs());
if (ISAFTERBR) {
// 赋值换行标记
comp.isAfterBr_ = ISAFTERBR;
ISAFTERBR = false;
}


comp.setBrHeight(brHeight_);
// br节点不连续,即使将br节点高度值清零
brHeight_ = 0;
// 所有控件的显示值存储在节点值中
comp.property_.put("text", cc.nodeValue_);
comp.initRealView(activity_, cc.nodeValue_);
comp.childrenList_ = new ArrayList<Component>(2);
comp.setTag(cc.nodeName_);
// 将控件加入控件集合
Component.VWIDGETARRAY.add(comp);
if (null != component) {
component.childrenList_.add(comp);
comp.setParent(component);
} else {
if (parseType_ == ENTIRE) {
ComponentCopy.COMPONENT = comp;
} else {
ComponentCopy.COMPONENTPARTLY = comp;
}
}


// 4、检查该控件是否存在子元素,如果是则遍历其子元素
int size = cc.getChildren().size();
for (int i = 0; i < size; i++) {
xmlToView(cc.getChild(i), comp);
}


}
} catch (Exception e) {
Utils.printException(e);
}
}


private void setClassField(Class c, String name, Object value) {
// TODO Auto-generated method stub
try {
Field field = null;
field = c.getDeclaredField(name);
field.set(field, value);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
Utils.printException(e);
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
Utils.printException(e);
} catch (SecurityException e) {
// TODO Auto-generated catch block
Utils.printException(e);
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
Utils.printException(e);
}
}


// 解析到Element的结尾时调用此方法
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
eventType_ = END_TAG;
String content = "";
if (null != buf_) {
content = buf_.toString().trim();
content = Utils.insteadOfSpecillCharacter(content, false);
}
if (localName.equalsIgnoreCase("style")) {
haveStyle_ = true;
// 读取界面的样式值,并赋给stylehash变量
CssStyle.STYLEHASH = CssStyle.parseStyle(content);
// 存储全局界面的样式,该栈元素始终唯一,保存当前全界面的样式
if (parseType_ == ENTIRE)
ENTIRESTACK.add(CssStyle.STYLEHASH);
// 清空节点值
buf_ = null;
return;
} else if (localName.equalsIgnoreCase("script")) {
if (null != content || !content.equals("")) {
// Component.LUASTATE.LdoString(content);
scriptStack_.add(content);
}
// 清空节点值
buf_ = null;
return;
}
if ((nodeNameStack_.indexOf("body") != -1) && (parseType_ == ENTIRE)) {
// 将该元素赋给静态变量,以备程序调用
if (!stack_.isEmpty() && null == ComponentCopy.CC)
ComponentCopy.CC = (ComponentCopy) stack_.get(0);
ComponentCopy cc = (ComponentCopy) stack_.peek();
cc.setValue(content);
displayStack_.pop();
// 将该节点出栈,使栈顶元素为其上层节点,方便其上层节点添加新的子元素
stack_.pop();
if (null != CssStyle.STYLEHASH) {
CssStyle cs = (CssStyle) CssStyle.STYLEHASH.get(cc.nodeAttrsMap_.get("class"));
insertLLVCode(cs);
}
} else if (parseType_ == PARTLY) {
if (localName.equalsIgnoreCase("head") || localName.equalsIgnoreCase("content"))
return;
if (!stack_.isEmpty()) {
ComponentCopy cc = (ComponentCopy) stack_.peek();
cc.setValue(content);
if (null == ComponentCopy.CC)
ComponentCopy.CC = (ComponentCopy) stack_.get(0);
}


displayStack_.pop();
// 将该节点出栈,使栈顶元素为其上层节点,方便其上层节点添加新的子元素
stack_.pop();
}
nodeNameStack_.pop();
// 清空节点值
buf_ = null;
}


/**
* 插入llV节点,该节点是android界面结构需要,手动加入,在服务端提供的xml报文中不会有体现
*
* @param cs
*/
private void insertLLVCode(CssStyle cs) {
// TODO Auto-generated method stub
// 取得控件样式position对应的值,决定是否插入llv节点,该控件纯粹是为了管理界面结构,没有任何表现形式.
if (null != cs && null != cs.position_) {
// 获取控件的position样式
if (!isInsertLLV_) {
// 更改标记,表示已执行插入操作
isInsertLLV_ = true;


// 在llv节点之前插入br节点,模拟换行效果
ComponentCopy tempBr = new ComponentCopy();
tempBr.setName("br");
((ComponentCopy) stack_.peek()).addChilds(tempBr);


// 尚未插入界面中部总管理器节点,在此执行插入操作
ComponentCopy temp = new ComponentCopy();
temp.setName("llv");
((ComponentCopy) stack_.peek()).addChilds(temp);
stack_.add(temp);
}
}
}


// 取得Element的中间夹的字符串
public void characters(char ch[], int start, int length) {
if (eventType_ == END_TAG && length > 1) {
// 如果紧接着end_tag后面有需要获取出来的数据则执行
readTextIndex_ = 0;
}
try {
eventType_ = TEXT;
if (readTextIndex_ == 0) {
// 节点计数器为零表示是第一次读取该节点值。应将以前读取的值全部清空。该处执行赋空操作,如果执行delete操作数据量大的话会引起内存溢出问题。
buf_ = null;
buf_ = new StringBuffer(10);
}
// 读取节点值
if (null != buf_)
buf_.append(ch, start, length);
// 节点值计数器累加
readTextIndex_++;


} catch (Exception e) {
// TODO Auto-generated catch block
Utils.printException(e);
}
}


/**
* @param atts
* @param attrName
* @return
*/
private final String getAttrString(Attributes atts, String attrName) {
String attr = null;
try {
attr = Utils.insteadOfSpecillCharacter(atts.getValue(attrName), false);
} catch (Exception e) {
Utils.printException(e);
}
return attr;
}

}


============================================================分割===============================

/**
* 读取本地文件main.xml,根据该文件显示界面内容,并决定程序的下一步动作
*/
private void readMainXml() {
// TODO Auto-generated method stub
String mainXml = Utils.getStringFormAsset(this, "main.xml");
initLuaScript();

//解析的具体实现,handler
AtomParser apc = new AtomParser(this, AtomParser.ENTIRE);
try {
//触发解析
android.util.Xml.parse(mainXml, apc);
setContentView(ComponentCopy.COMPONENT.getLPView());
} catch (SAXException e) {
// TODO Auto-generated catch block
Utils.printException(e);
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值