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(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);
        }
    }

你可能感兴趣的:(Android技术总结)