XML的三种解析方式

XML简介

XML,可扩展标记语言(Extensible Markup Language),标准通用语言的子集。XML可以用来标记数据、定义数据类型。它非常适合互联网传输,提供了统一的方法来描述和交换独立于应用程序和供应商的结构化语言。


XML特点

  • 是一种标记语言,类似于HTML
  • 设计宗旨是传输数据,而非显示数据
  • 没有预定义的标签,需要自定义标签
  • 具有自我描述性
  • 是W3C推荐的标准

XML格式

XML可以用来存储少量的数据,在网络层也可以作为服务端与客户端之间数据传输的一种格式。

<?xml version="1.0" encoding="UTF-8"?>
<root>                                                 
    <child>
        <subChild></subChild>
    </child>
</root>
需要解析的文件menu.xml
<?xml version="1.0" encoding="UTF-8"?>
<Menu>
    
    <list  name="热销榜">
        <food>鱼香肉丝</food>
        <food>酸辣土豆丝</food>
        <food>干煸刀豆</food>
        <food>刀豆土豆</food>
        <food>韭黄炒蛋</food>
        <food>椒盐排条</food>
    </list>

    <list  name="限时特价">
        <food>酸汤肥牛</food>
        <food>青椒肉丝毛豆</food>
        <food>红烧小肉</food>
        <food>干锅牛蛙</food>
        <food>水芹香干</food>
        <food>剁椒秋刀鱼</food>
    </list>
    
    <list  name="经济实惠">
        <food>水煮鱼片</food>
        <food>干煎臭豆腐</food>
        <food>鱼香茄子</food>
        <food>香酥蚕豆堡</food>
        <food>外婆菜窝窝头</food>
        <food>毛血旺</food>
    </list>
    
</Menu>

XML的DOM解析

DOM解析会将整个XML文件中的内容以树的形式加载到内存,然后可以进行遍历树检索到需要的数据。
实现解析的套路:

1.获得解析器工厂类
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
2.获得解析器类
DocumentBuilder builder = factory.newDocumentBuilder();
3.将需要解析的XML文件传入解析器
Document doc = builder.parse("data.xml");
4.获得文档根元素
Element root = doc.getDocumentElement();
5.获取根节点下的元素集合,取出数据并保存
NodeList list = root.getChildNodes();

Document的一些API:

  • NodeList:节点列表类,包含一个或多个Node的列表。
  • Node:抽象节点类,通常调用其子节点Element,Attr,Text。
  • Element:元素类,getTagName获取节点名
  • Attr:属性类,代表某个元素的属性

XML的Sax解析

Sax解析是对xml文件进行逐行解析,相对于DOM解析方式效率要高。
Sax解析的常用套路:
1.获得解析器工厂

SAXParserFactory factory = SAXParserFactory.newInstance();

2.通过解析器工厂获得Sax解析器对象

SAXParser parser = factory.newSAXParser();

3.创建处理器MyHandler继承自DefaultHandler,实现其内部的处理方法

class MyHandler extends DefaultHandler{

    @Override
    public void startDocument() throws SAXException {
        //do something
    }

    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        //do something
    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        //do something
    }

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        //do something
    }
}

4.对文档输入流(InputStream)进行解析

parser.parse(is, handler);

使用Sax方式对menu.xml文件进行Pull解析
关键java代码:

private List<String> menu;

private HashMap<String, List<String>> map;

SAXParserFactory factory = SAXParserFactory.newInstance();
        
try {
    SAXParser parser = factory.newSAXParser();
    
    InputStream is = getAssets().open("menus.xml");
    
    MyHandler handler = new MyHandler();
    
    parser.parse(is, handler);
} catch (Exception e) {
    e.printStackTrace();
}

MyHandler.java

class MyHandler extends DefaultHandler{
        
    String tagName = null; 

    @Override
    public void startDocument() throws SAXException {
        map = new HashMap<String, List<String>>();
    }

    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {
        tagName = qName;
        if("list".equals(qName)){
            menu = new ArrayList<String>();
            name = attributes.getValue("name");
        }
        
    }

    @Override
    public void endElement(String uri, String localName, String qName)
            throws SAXException {
        tagName = "";
        if("list".equals(qName)){
            map.put(name, menu);
        }
    }

    @Override
    public void characters(char[] ch, int start, int length)
            throws SAXException {
        String value = new String(ch,start,length);
        if("food".equals(tagName)){
            menu.add(value);
        }
    }
}

XML的Pull解析

Pull解析的常用套路:
1.通过解析器工厂获得pull解析器对象

XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();

2.设置需解析的输入流(InputStream)和编码方式

parser.setInput(is,"utf-8");

3.获取事件类型

int eventType = parser.getEventType();

4.根据事件类型和标签名做出相应处理,如读取和保存数据

while(eventType != XmlPullParser.END_DOCUMENT) {
    // 获得当前节点的名称
    String tagName = parser.getName();      
    switch (eventType) {
        // 当前等于开始节点
        case XmlPullParser.START_TAG:         
           //相关操作         
           break;
        // 当前等于结束节点
        case XmlPullParser.END_TAG:                
           //相关操作          
           break;

        default:
           break;
    }
    // 下一个
    eventType = parser.next();
}

使用Pull方式对menu.xml文件进行Pull解析
关键java代码:

private List<String> menu;

private HashMap<String, List<String>> map;

XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
            
InputStream is = getAssets().open("menus.xml");

parser.setInput(is,"utf-8");

int type = parser.getEventType();

while(type != XmlPullParser.END_DOCUMENT){
    switch (type) {
    case XmlPullParser.START_DOCUMENT:
        map = new HashMap<String, List<String>>();
        break;
    case XmlPullParser.START_TAG:
        if("list".equals(parser.getName())){
            menu = new ArrayList<String>();
            name = parser.getAttributeValue(0);
        }else if("food".equals(parser.getName())){
            menu.add(parser.nextText());
        }       
        break;
    case XmlPullParser.END_TAG:
        if ("list".equals(parser.getName())) {
            map.put(name, menu);
        }
        break;
    default:
        break;
    }
    type = parser.next();
    
}

总结

本文介绍了一些主流XML文件解析的方式,分别是DOM解析、SAX解析和PULL解析。因为PULL解析是Google官方推荐的,所以也是我们平时做Android开发最常用的一种。即使这样,我们还是对其他的解析方式及其优缺点有所了解。

  • Dom解析的优点:将整个文档加载到内存中,便于删除、修改、查询的等相关操作。

  • Dom解析的缺点:内存中充满很多无用的节点,浪费资源

  • Sax解析的优点:基于事件驱动解析,无需将整个文档加载到内存中,效率高。

  • Sax解析的缺点:事件过去后,数据没有保存就会丢失。

  • Pull解析:兼容了Dom解析和Sax解析的优点,是谷歌官方推荐使用的Xml解析方式。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容