android中XML的解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gongzhiyao3739124/article/details/52790953

XML即可扩展标记语言,它和HTML很类似,但是又与HTML有很多不同之处,XML用于传输和存储数据,而HTML则是为了显示数据,单从代码上来看,XML最大的特点就是标签没有被预定义,不像HTML那样必须使用固定的预定义元素集。

上面也说到了,XML是用来存储数据的,这时候就不得不与同时具有存储功能的JSON格式来进行一下对比了。

1.在可读性方面,JSON和XML的可读性基本相同。

2.在扩展性方面,XML和Json同时具有较好的扩展性,没有什么是XML能够扩展,而JSON不能的。

3.在解码难度方面,XML解析时,需考虑子节点和父节点,而JSON的解码难度几乎为0。

4.在数据体积大小方面,JSON相对于XML来说,数据的体积小,传输的速度更快些。

5.在数据交互方面,JSON和JavaScript的交互更加方便,更容易解析处理,具有更好的数据交互。


上面只是简单的挑拣了几条他们之间的区别,更多的区别希望大家在使用的过程中自己体会。

下面再给大家说一下XML严格定义的语法要求:

1.关于XML元素的命名

名称可以含字母,数字以及其他的字符,但不能够以数字或者标点符号开始,下划线除外。

名称不能够以xml(XML,Xml,xmL等)开始。

名称不能够包含空格。

可使用任何的名称,没有保留的字词。

2.XML文档必须有根元素

3.每个开始标签必须要有一个结束标签

4.所有的标签都要区分大小写

5.所有的标签都必须合理嵌套

6.所有标签的属性值必须用双引号或者单引号包括起来

7.在XML中文档中的空格不会被删除,会被原样保留下来

8.关于XML实体的问题

在XML中一些字符拥有特殊的意义,例如,若把"<"放在XML元素中,会发生错误,这是因为解析器会把它当作新元素的开始。错误如下:

<note>if count < 10 then </note>

这就是非法的,为此,需要使用实体引用来代替"<"字符。即:

<note>if count  &lt; 10 then </note>

在XML中有五个预定义的实体引用,虽然在XML中只有字符<和&时非法的,但是还是鼓励大家把实体引用代替作为一个好习惯。




好了现在我们来说一下,在Android中时如何解析XM了格式的。

在Android中,XML文件解析最常用的有DOM,SAX,PULL3中解析方式,下面就分别来介绍这3中解析方式。


一、DOM解析XML

DOM解析XML文件时,会将XML文件的所有内容以文档树的方式存放在内存中,然后允许用户使用DOM API遍历XML树,检索所需的数据。

由于解析时会把所有的文件读入内存,所以内存消耗较大,尤其是在Android移动设备上。所以建议使用SAX和PULL进行解析,但是如果XML文件内容较小的话,采用DOM也是可行的。

DOM解析XML文件的基本思路如下:

1)利用DocumentBuilderFactory创建一个DocumentBuilderFactory实例。

2)利用DocumentBuilderFactory创建一个DocumentBuilder。

3)加载XML文档(Document)。

4)获取文档的根节点(Element)。

5)获取根节点中所有的列表(NodeList)。

6)获取子节点列表中所需要读取的点。

本次示例给大家解析一下assets目录下的city.xml文件,文件内容如下:

<?xml version="1.0"?>

   <citys>

          <city id="0">

                    <name>Alaska</name>

                    <code>907</code>

          </city>

          <city id="1">

                    <name>Chicago</name>

                    <code>312</code>

          </city>

          <city id="3">

                    <name>Hawaii</name>

                    <code>808</code>

          </city>

</citys>

首先先定义一个实体类City,其中包括对应属性的set和get方法,具体代码如下:

public class City {
    private String name;
    private String code;
    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "City [name="+name+",code="+code+",id="+id+"]";
    }
}


使用DOM解析的具体操作如下:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "DomParseXml";
    private static final String CITY_NAME = "name";
    private static final String CITY_ID = "id";
    private static final String CITY_CODE = "code";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        parseXml();
    }

    private List<City> parseXml() {
        List<City> Citys = new ArrayList<City>();
        DocumentBuilder builder;
        DocumentBuilderFactory factory = null;
        Document document = null;
        InputStream inputStream = null;
        factory = DocumentBuilderFactory.newInstance();
        try {
            builder = factory.newDocumentBuilder();
            inputStream = getResources().getAssets().open("city.xml");
            document = builder.parse(inputStream);
            Element root = document.getDocumentElement();
            NodeList nodes = root.getElementsByTagName("city");
            City city = null;
            for (int i = 0; i < nodes.getLength(); i++) {
                city = new City();
                Element cityElement = (Element) nodes.item(i);
                city.setId(cityElement.getAttribute(CITY_ID));
                Element cityNameElement = (Element) cityElement.getElementsByTagName(CITY_NAME).item(0);
                city.setName(cityNameElement.getFirstChild().getNodeValue());
                Element cityCodeElement = (Element) cityElement.getElementsByTagName(CITY_CODE).item(0);
                city.setCode(cityCodeElement.getFirstChild().getNodeValue());
                Citys.add(city);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return Citys;
    }
}


二、SAX解析XML

SAX是基于事件驱动的,边加载边解析,当然Android的事件机制是基于回调函数的,在使用SAX解析XML文档时,在读取到文档开始和结束标签时就会回调一个事件,在读取到其他节点与内容的时候也会回调一个事件。

在SAX解析XML时,需要通过XMLReader和DefaultHandler的配合,基本思路如下:

1)创建SAXParserFactory对象。

2)根据SAXParserFactory.newSAXParser()方法返回一个SAXParser解析器。

3) 根据SAXParser解析器获取事件源对象XMLReader。

4)实例化一个DefaultHandler对象。

5)连接事件源对象XMLReader到事件处理类DefaultHandler。

6)调用XMLReader的parse方法从输入源中获取XML数据。

7)通过DefaultHandler返回需要的数据集合。


这次的示例时在Raw目录下的link.xml文件。内容如下:

<?xml version="1.0"?>

  <p>

          <a  href="http://news.baidu.com" name="tj_news">新闻</a>

          <a  href="http://www.baidu.com" name="tj_news">网页</a>

          <a  href="http://tieba.baidu.com" name="tj_news">贴吧</a>

          <a  href="http://zhidao.baidu.com" name="tj_news">知道</a>

          <a  href="http://imge.baidu.com" name="tj_news">图片</a>

                                                           ......

                                                           ......

  </p>

同样,像DOM解析一样,同样需要实现一个实体类Link,然后实现所有属性的set和get方法。

这里就不在赘述了。现在来看一下通过SAX方式解析XML。

private void parseXml() {
    SAXParserFactory factory=SAXParserFactory.newInstance();
    SAXParser parser;
    SAXParserHelper helper=null;
    try {
        parser=factory.newSAXParser();
        XMLReader xmlReader=parser.getXMLReader();
        helper=new SAXParserHelper();
        xmlReader.setContentHandler(helper);
        InputStream stream=getResources().openRawResource(R.raw.link);
        InputSource is=new InputSource(stream);
        xmlReader.parse(is);
        
    } catch (ParserConfigurationException e) {
        e.printStackTrace();
    } catch (SAXException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    helper.getLinks();

}

上面代码中自定义的SAX解析的帮助类SAXParserHelper

public class SAXParserHelper extends DefaultHandler {
    private static final String TAG = "SAXParserHelper";
    List<Link> Links;
    Link link;
    int currentState = 0;

    public List<Link> getLinks() {
        for (int i = 0; i < Links.size(); i++) {
            Log.d(TAG, Links.toString());
        }
        return Links;
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
        String theString = String.valueOf(ch, start, length);
        if (currentState != 0) {
            link.setText(theString);
            currentState = 0;
        }
        return;
    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
        if (localName.equals("a")) {
            Links.add(link);
        }
    }

    @Override
    public void startDocument() throws SAXException {
        super.startDocument();
        Links = new ArrayList<Link>();
    }


    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
        link = new Link();
        if (localName.equals("a")) {
            for (int i = 0; i < attributes.getLength(); i++) {
                if (attributes.getLocalName(i).equals("href")) {
                    link.setHref(attributes.getValue(i));
                } else if (attributes.getLocalName(i).equals("name")) {
                    link.setName(attributes.getValue(i));
                }
            }
            currentState = 1;
            return;
        }
        currentState = 0;
        return;
    }
}

三、PULl解析XML

PULL解析XML的方式与SAX解析XML的方式是一样的,都是基于事件驱动的,使用PULL解析器解析时应注意一下几点:

1)通过xml.newPullParser()获得解析器

2)通过parser.setInput(in,"UTF-8")设置输入流以及编码方式

3)通过parser.next()获取下一个元素并触发相应事件


此次示例使用的是

<?xml version="1.0"?>

<poem lang="chinese">

<title>静夜思</title>

<author>李白</author>

<content>床前明月光,疑是地上霜。举头望明月,低头思故乡。</content>

</poem>

针对上面的XML文本,使用PuLL那个是解析的代码如下:

private void parseXml() {
    XmlPullParserFactory factory;
    try {
        factory = XmlPullParserFactory.newInstance();
        //设置支持名称空间
        factory.setNamespaceAware(true);
        XmlPullParser xpp = factory.newPullParser();
        //xmlStringxml中的内容,格式为String
        xpp.setInput(new StringReader(xmlString));
        int eventType = xpp.getEventType();
        while (eventType == XmlPullParser.END_DOCUMENT) {
            if (eventType == XmlPullParser.START_DOCUMENT) {
                Log.d(TAG,"start document");
            }else if(eventType==XmlPullParser.START_TAG){
                Log.d(TAG,"start tag"+xpp.getName());
            }else if(eventType==XmlPullParser.END_TAG){
                Log.d(TAG,"End tag"+xpp.getName());
            }else if(eventType==XmlPullParser.TEXT){
                Log.d(TAG,"Text "+xpp.getText());
            }
            eventType=xpp.next();

        }
    } catch (XmlPullParserException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    Log.d("TAG","End document");

}







展开阅读全文

没有更多推荐了,返回首页