首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >4--安卓网络编程之XML总汇篇

4--安卓网络编程之XML总汇篇

作者头像
张风捷特烈
发布2018-10-25 15:02:44
6560
发布2018-10-25 15:02:44
举报
零、前言

Xml是一种应用广泛的标记语言,我们常见的html便是它的子集。形如:<XXX>xxx</XXX>组成的闭合标签 安卓的res目录下的xml想必大家都是否熟悉,它们最终都是在代码中被读取并解析发挥效果的 安卓的SharedPreferences是以Xml的形式存储数据的,就连AndroidManifest注意一看也是Xml 可以说xml涉及到了安卓的很多方面,我们并不陌生,Xml最大的好处就是解耦,容易复用和更换

pull解析.png

XML常见的三种解析方式:

解析方式

加载驱动方式

可修改?

自定义结束?

效率

备注

Pull解析

事件驱动

安卓专有

Sax解析

事件驱动

Dom解析

直接全部加载

解析时构建dom树

准备的待解析xml:
<?xml version="1.0" encoding="UTF-8"?>
<weapons>
    <weapon material="玉" type="剑">
        <name>问天剑</name>
        <atk>2000</atk>
        <user>语熙华</user>
    </weapon>
    <weapon material="铁" type="刀">
        <name>皇刀</name>
        <atk>3000</atk>
        <user>九方玄玉</user>
    </weapon>
</weapons>

一、Pull解析概述
Pull是安卓内置的,基于事件触发的解析器
Pull解析器小巧轻便,解析速度快,简单易用
主动从解析器中获取事件,可以在满足了需要的条件后不再获取事件,结束解析
1、Pull解析Xml:
private ArrayList<WeaponXml> parseXmlWithPull() {
    InputStream is = null;
    try {
        //XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        //XmlPullParser pullParser = factory.newPullParser();
        //获得Xml解析器--等价上两句
        XmlPullParser pullParser = Xml.newPullParser();
        //得到一个含有xml的is输入流
         is = getAssets().open("weapon.xml");
        //设置输入流
        pullParser.setInput(is, "utf-8");
        //触发第一个事件:eventType=0 即:START_DOCUMENT
        int eventType = pullParser.getEventType();
        //没有读到文档结束之前都在while里走
        while (eventType != XmlPullParser.END_DOCUMENT) {
            switch (eventType) {//根据事件类型执行
                case XmlPullParser.START_DOCUMENT://文档开始
                    //新建对象的集合
                    mWeapons = new ArrayList<>();
                    break;
                case XmlPullParser.START_TAG://读到第一个标签时再进行switch选择
                    switch (pullParser.getName()) {//拿到标签名称
                        case "weapon"://如果标签是weapon
                            //新建一个 Weapon对象用来记录信息
                            mWeapon = new WeaponXml();
                            //获取第一个属性值
                            String material = pullParser.getAttributeValue(0);
                            //获取第二个属性值
                            String type = pullParser.getAttributeValue(1);
                            //对象装载得到的属性
                            mWeapon.setType(type);
                            mWeapon.setMaterial(material);
                            break;
                        case "name":
                            //对于没有属性的标签,可以用nextText获取标签内部的文字
                            String name = pullParser.nextText();
                            mWeapon.setName(name);
                            break;
                        case "atk":
                            Short atk = new Short(pullParser.nextText());
                            mWeapon.setAtk(atk);
                            break;
                        case "user":
                            String user = pullParser.nextText();
                            mWeapon.setUser(user);
                            break;
                    }
                    break;
                case XmlPullParser.END_TAG://当事件类型是终止标签时:即</XXX>
                    if ("weapon".equals(pullParser.getName())) {
                        mWeapons.add(mWeapon);//将生成对象加入集合,一个
                    }
                    break;
            }
            eventType = pullParser.next();//解析下一元素,更新event
        }
    } catch (Exception e) {
        e.printStackTrace();
    }finally {
        if (is != null) {
            try {
                is.close();//关流
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return mWeapons;
}
2、Pull写入Xml:
    /**
     * 备份Xml--当然也可以备份任意的实体类作为Xml,比如短信,联系人
     */
    private void backUpXml() {
        ArrayList<WeaponXml> weapons = parseXmlWithPull();
        XmlSerializer serializer = Xml.newSerializer();
        FileOutputStream fos = null;
        try {
            String path = Environment.getExternalStorageDirectory().getAbsolutePath();
             fos = new FileOutputStream(path + File.separator + "weapon.xml");

            serializer.setOutput(fos, "utf-8");
            //文档开始
            serializer.startDocument("utf-8", true);
            serializer.startTag("", "weapons");
            for (WeaponXml weapon : weapons) {
                //新建标签: <weapon>
                serializer.startTag(null, "weapon");
                //设置属性: material="玉" type="剑"

                serializer.attribute("","material", weapon.getMaterial());
                serializer.attribute("","type", weapon.getType());
                //嵌套子标签:<name>问天剑</name>
                serializer.startTag(null, "name");
                serializer.text(weapon.getName().trim());
                serializer.endTag(null, "name");

                serializer.startTag(null, "atk");
                serializer.text(weapon.getAtk() + "");
                serializer.endTag(null, "atk");

                serializer.startTag(null, "user");
                serializer.text(weapon.getUser().trim());
                serializer.endTag(null, "user");
                //终止标签: </weapon>
                serializer.endTag(null, "weapon");
            }
            serializer.endTag("", "weapons");//标签结束
            serializer.endDocument();//文档结束
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

二、Sax解析概述:(Simple API for XML)
Sax解析方式会逐行地去扫描XML文档,当遇到标签时会触发解析处理器,采用事件处理的方式解析XML 
优点:在读取文档的同时即可对XML进行处理,不必等到文档加载结束,相对快捷,所以可以解析超大XML
缺点:只能用来读取XML中数据,无法进行增删改。
1、Sax解析Xml
/**
 * 
 * @return
 */
private ArrayList<WeaponXml> parseXmlWithSax() {
    InputStream is = null;
    mWeapons = new ArrayList<>();
    try {
        SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
        is = getAssets().open("weapon.xml");
        saxParser.parse(is, new DefaultHandler() {
            /**
             *  开始标签时
             * @param uri 命名空间
             * @param localName 标签名
             * @param qName 全名(带命名空间的标签的名字)
             * @param attributes 属性
             * @throws SAXException
             */
            @Override
            public void startElement(String uri, String localName,
                                     String qName, Attributes attributes) throws SAXException {
                //"属性名:" + attributes.getLocalName(i)
                //"属性值:" + attributes.getValue(i));
                if ("weapon".equals(localName)) {
                    mWeapon = new WeaponXml();
                    mWeapon.setMaterial(attributes.getValue(0));
                    mWeapon.setType(attributes.getValue(1));
                }
                mPerTag = localName;
            }
            /**解析标签的内容的时候调用
             *
             * @param ch 当前文本节点的字节数组
             * @param start 字节开始的位置 默认 0 全部读取
             * @param length 长度
             * @throws SAXException
             */
            @Override
            public void characters(char[] ch, int start, int length) throws SAXException {
                String chars = new String(ch, start, length).trim();
                if ("name".equals(mPerTag)) {
                    mWeapon.setName(chars);
                } else if ("atk".equals(mPerTag)) {
                    mWeapon.setAtk(Integer.parseInt(chars));
                } else if ("user".equals(mPerTag)) {
                    mWeapon.setUser(chars);
                }
            }
            /**
             * 标签解析结束调用
             * @param uri
             * @param localName
             * @param qName
             * @throws SAXException
             */
            @Override
            public void endElement(String uri, String localName, String qName) throws SAXException {
                if ("weapon".equals(localName)) {
                    mWeapons.add(mWeapon);
                    mWeapon = null;
                }
                mPerTag = null;
            }
        });
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return mWeapons;
}

2、Sax存储Xml
/**
 * sax创建Xml文件
 */
private void saxCreateXml() {
    ArrayList<WeaponXml> weaponXmls = parseXmlWithSax();
    //1、创建一个SAXTransformerFactory的对象
    SAXTransformerFactory saxTF = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
    FileOutputStream fos = null;
    try {
        //创建一个Transformer对象
        TransformerHandler handler = saxTF.newTransformerHandler();
        Transformer transformer = handler.getTransformer();
        transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        String path = Environment.getExternalStorageDirectory().getAbsolutePath();
        fos = new FileOutputStream(path + File.separator + "weaponSax.xml");
        StreamResult result = new StreamResult(fos);
        handler.setResult(result);
        //开始
        handler.startDocument();
        AttributesImpl atts = new AttributesImpl();
        handler.startElement("", "", "weapons", atts);
        for (WeaponXml weaponXml : weaponXmls) {
            atts.clear();
            atts.addAttribute("", "", "material", "", weaponXml.getMaterial());
            atts.addAttribute("", "", "type", "", weaponXml.getType());
            handler.startElement("", "", "weapon", atts);
            atts.clear();
            handler.startElement("", "", "name", atts);
            handler.characters(weaponXml.getName().toCharArray(), 0, weaponXml.getName().length());
            handler.endElement("", "", "name");
            atts.clear();
            handler.startElement("", "", "atk", atts);
            String atk = String.valueOf(weaponXml.getAtk());
            handler.characters(atk.toCharArray(), 0, atk.length());
            handler.endElement("", "", "atk");
            atts.clear();
            handler.startElement("", "", "user", atts);
            handler.characters(weaponXml.getUser().toCharArray(), 0, weaponXml.getUser().length());
            handler.endElement("", "", "user");
            handler.endElement("", "", "weapon");
        }
        handler.endElement("", "", "weapons");
        //关闭document
        handler.endDocument();
    } catch (Exception e) {
        e.printStackTrace();
    }finally {
        if (fos != null) {
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

三、DOM解析概述:
DOM将整个XML文件加载到内存中,并构建出节点树;
应用程序可以通过遍历节点树的方式来解析XML文件中的各个节点、属性等信息;
优点:对XML节点的添加修改等,而且解析也很方便
缺点比较耗费内存,解析速度也不快
1、dom解析Xml
    /**
     * dom解析Xml
     * @return
     */
    private ArrayList<WeaponXml> parseXmlWithDom() {
         mWeapons = new ArrayList<>();
        InputStream is = null;

        try {
            is = getAssets().open("weapon.xml");
            //获取document对象
            Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is);
            //获取根元素
            Element root = dom.getDocumentElement();
            //获取weapon节点
            NodeList weaponNode = root.getElementsByTagName("weapon");
            for (int i = 0; i < weaponNode.getLength(); i++) {
                mWeapon = new WeaponXml();
                //获取person下第i个元素
                Element weaponEl = (Element) weaponNode.item(i);
                String material = weaponEl.getAttribute("material");//得到第i个属性值
                String type = weaponEl.getAttribute("type");//得到第i个属性值

                mWeapon.setMaterial(material);
                mWeapon.setType(type);

                NodeList childNodes = weaponEl.getChildNodes();//获得获取weapon下子元素

                for (int j = 0; j < childNodes.getLength(); j++) {

                    if (childNodes.item(j).getNodeType() == Node.ELEMENT_NODE) {
                        String nodeName = childNodes.item(j).getNodeName();
                        if ("name".equals(nodeName)) {
                            String name = childNodes.item(j).getFirstChild().getNodeValue();
                            mWeapon.setName(name);
                        } else if ("atk".equals(nodeName)) {
                            String atk = childNodes.item(j).getFirstChild().getNodeValue();
                            mWeapon.setAtk(Integer.parseInt(atk));
                        } else if ("user".equals(nodeName)) {
                            String user = childNodes.item(j).getFirstChild().getNodeValue();
                            mWeapon.setUser(user);
                        }
                    }
                }
                mWeapons.add(mWeapon);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mWeapons;
    }

2、dom存储Xml
    /**
     * sax创建Xml文件
     */
    private void domCreateXml() {
        try {
            ArrayList<WeaponXml> weaponXmls = parseXmlWithDom();

            //创建Dom解析器
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

            //新建空白文档
            Document doc = builder.newDocument();
            //建立根元素employees
            Element root = doc.createElement("weapons");
            //将根节点添加进入文档
            doc.appendChild(root);

            for (WeaponXml weaponXml : weaponXmls) {
                Element weapon = doc.createElement("weapon");
                weapon.setAttribute("material", weaponXml.getMaterial());
                weapon.setAttribute("type", weaponXml.getType());
                root.appendChild(weapon);

                Element name = doc.createElement("name");
                name.appendChild(doc.createTextNode(weaponXml.getName()));
                weapon.appendChild(name);


                Element atk = doc.createElement("atk");
                atk.appendChild(doc.createTextNode(weaponXml.getAtk()+""));
                weapon.appendChild(atk);

                Element user = doc.createElement("user");
                user.appendChild(doc.createTextNode(weaponXml.getUser()));
                weapon.appendChild(user);
            }

            //为了得到xslt引擎创建对象
            TransformerFactory tff = TransformerFactory.newInstance();
            //创建xslt引擎对象输出xml文档
            Transformer tf = tff.newTransformer();
            //获取属性对象
            Properties pro = tf.getOutputProperties();
            //设置编码格式和输出格式
            pro.setProperty(OutputKeys.ENCODING, "utf-8");
            pro.setProperty(OutputKeys.METHOD, "xml");
            tf.setOutputProperties(pro);
            //创建资源对象
            DOMSource source = new DOMSource(doc);
            String path = Environment.getExternalStorageDirectory().getAbsolutePath()
                    +File.separator+"WeaponDom.xml";
            //获得输出对象
            StreamResult result = new StreamResult(new File(path));
            //执行dom文档到xml文件转换
            tf.transform(source, result);
        } catch (Exception e) {
            e.printStackTrace();
        }


后记:捷文规范
1.本文成长记录及勘误表

项目源码

日期

备注

V0.1--无

2018-10-15

4--安卓网络编程之XML总汇篇

2.更多关于我

笔名

QQ

微信

爱好

张风捷特烈

1981462002

zdl1994328

语言

我的github

我的简书

我的CSDN

个人网站

3.声明

1----本文由张风捷特烈原创,转载请注明 2----欢迎广大编程爱好者共同交流 3----个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正 4----看到这里,我在此感谢你的喜欢与支持

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.10.17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 零、前言
    • XML常见的三种解析方式:
      • 准备的待解析xml:
      • 一、Pull解析概述
        • 1、Pull解析Xml:
          • 2、Pull写入Xml:
          • 二、Sax解析概述:(Simple API for XML)
            • 1、Sax解析Xml
              • 2、Sax存储Xml
              • 三、DOM解析概述:
                • 1、dom解析Xml
                  • 2、dom存储Xml
                  • 后记:捷文规范
                    • 1.本文成长记录及勘误表
                      • 2.更多关于我
                        • 3.声明
                        相关产品与服务
                        对象存储
                        对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档