XML简介

网上有很多优秀的XML教程,想学习详细知识的同学可以去搜索学习一下,比如W3CSchool网站(链接: W3CSchool XML教程.)本文就是我自己在W3CSchool学习总结的一篇文章。

一、什么是XML?

  • XML:可扩展标记语言(eXtensible Markup Language),这名称不用记没啥用,知道可扩展就行。

二、XML是干什么的?

  • 很简单就是设计用来存储和传输数据的。

三、XML特点,和HTML对比

XMLHTML
可扩展标记语言超文本标记语言
标签自定义标签不可自定义
用来存储和传输数据重点在于数据内容用来显示数据,重点在于显示的外观
用来存储和传输数据用来显示数据
树结构树结构

四、XML用途

  • 简化了数据的共享和传输

    可以理解XML就是给数据提供了一个标准规范,让数据按照XML的标准保存和传输。然后各个平台就可以通过用XML的标准去处理这些数据,从而达到数据可以跨平台共享。

  • 使数据更独立。

    XML数据被保存在本地,可以直接被访问和修改。相当于脱离了各个平台的业务逻辑,完全解耦脱离出来,处理起来更灵活。

  • 可以被用来创建新的语言。

    因为他的可扩展性,标签可以自己定义,所以也可以自己创建一门自己的语言。比如XHTML。

五、XML语法

具体语法可以参考链接:XML语法.

  1. 必须有关闭标签。HTML中可以没有。
  2. XML标签必须正确嵌套。
  3. 对大小写敏感,所以不要太随意了,平时就养成准确使用大小写的习惯最好。
  4. 必须有根元素。树结构的,树没有根怎么长是吧!
  5. 属性值必须用引号包裹,单引号还是双引号看实际使用。
  6. 某些特殊字符需要使用其他字符代替,比如小于号‘<’需要用 < 表示,具体还有哪些使用的时候查即可。记不住啊…
  7. 注释语法和HTML差不多一样一样的,
<!-- 这是一行注释 -->
  1. 空格不会被删减,换行用LF。
  2. 标签命名规则:链接:XML标签命名规则

六、DTD 、XML Schema

  • DTD全称为,Document Type Definition,中文翻译为文档类型定义,就是一套规则,用来定义如何创建标记语言的标签,一套标签的定义规则。
  • XML Schema 作用是定义 XML 文档的合法构建模块,类似 DTD。就是和DTD是同样的东西,只不过是只能用于定义XML用的,用来替代DTD来定义XML。
  • DTD教程
  • XML Schema教程

七、XML命名空间

  • 规则:xmlns:前缀=“URI”。
  • 命名空间是用来解决元素名称冲突的。
  • 命名空间定义在元素的开始标签者根标签的 xmlns 属性中
  1. 根标签中使用命名空间:
<root xmlns:h="http://www.w3.org/TR/html4/"
xmlns:f="//www.w3cschool.cn/furniture">

<h:table>
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>

<f:table>
<f:name>African Coffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>

</root> 
  1. 开始标签中使用命名空间:
<root>

<h:table xmlns:h="http://www.w3.org/TR/html4/">
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>

<f:table xmlns:f="//www.w3cschool.cn/furniture">
<f:name>African Coffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>

</root> 

上面的例子就是出现了相同名称的元素标签

所以通过在根标签或者开始标签添加命名空间来标识区分标签。

  • 注释:命名空间中的URL不会被解释器用来查找信息。目的只是用来给命名空间一个唯一的标识。不过,平常使用的时候都会作为把URL当做指针来使用,命名空间指向实际存在的网页活资源,这个网页或者资源包含关于命名空间的信息。

八、XML解析

解析XML,就是更具XML的树形结构对XML文档进行增删改查的操作。可以理解为利用某种API对XML文档进行编辑操作。

8.1、DOM解析

基于树形结构,和文档驱动,需要解析前先把xml数据保存到内存中。

  1. 什么是DOM
    DOM(Document Object Model 文档对象模型)定义了访问和操作文档的标准方法。
  2. XML DOM
    (1)定义了访问和操作XML文档的标准方法。
    (2)XML DOM把XML文档当中树形结构来看待,可以利用定义好的标准方法,对XML中的元素进行删除、增加、查询和修改操作。元素以及他们的属性都被称为节点。
  3. Android 中DOM解析XML(其他JS中进行解析请参考:JS中进行DOM解析里面有相关代码,或者百度去吧,我也不会…)
    xmlTest.xml文件(放入Android的assets文件夹下)代码如下:
<?xml version="1.0" encoding="utf-8"?>
<books>
    <book id="1">
        <name>钢铁是怎样练成的</name>
        <author>尼古拉.奥斯特洛夫斯基</author>
    </book>
    <book id="2">
        <name>三国演义</name>
        <author>罗贯中</author>
    </book>
    <book id="3">
        <name>水浒传</name>
        <author>施耐庵</author>
    </book>
</books>

解析代码如下:

public void getXMLData() throws IOException {
        InputStream inputStream = null;
        try {
             inputStream = this.getAssets().open("xmlTest.xml");
            //第一步,创建DocumentBuilderFactory工厂对象
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            //第二步,通过工厂对象创建DocumentBuilder建造者
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            //第三步,创建Document存放整个xml的数据
            Document document = documentBuilder.parse(inputStream);
            //第四步,获取xml根节点
            Element element = document.getDocumentElement();
            //第五步,使用根节点和子节点名称获取所有子节点为‘book’的节点
            NodeList bookList = element.getElementsByTagName("book");


            //第一种方式通过Element和具体标签名获取值
            for (int i = 0; i < bookList.getLength(); i++) {
                //获取某个book标签元素
                Element book = (Element) bookList.item(i);
                //获取标签的id属性,并显示到TextView上
                mTextView.append(book.getAttribute("id"));
                //更具标签名获取name标签信息
                NodeList bookName = book.getElementsByTagName("name");
                //因为name没有子节点了所以省略了遍历直接取了第一个值,拿到name节点
                Node item = bookName.item(0);
                //获取name值并显示到TextView上
                mTextView.append("书名:" + item.getTextContent() + "\n");

                NodeList author = book.getElementsByTagName("author");
                Node authorItem = author.item(0);
                mTextView.append("作者:" + authorItem.getTextContent() + "\n\n");
            }
            //添加分隔线
            mTextView.append("\n --------------------------------------------------\n\n");

            //第二种方式通过Node节点获取值
            for (int i = 0; i < bookList.getLength(); i++) {
                //获取某个book标签节点
                Node book = bookList.item(i);
                //获取标签的属性列表,并显示到TextView上
                NamedNodeMap attributes = book.getAttributes();
                Node id = attributes.getNamedItem("id");
                mTextView.append(id.getTextContent());
                //获取book节点的子节点
                NodeList bookInfos = book.getChildNodes();
                for (int j = 0; j < bookInfos.getLength(); j++) {
                    //获取某个子节点
                    Node bookInfo = bookInfos.item(j);
                    //判断节点名
                    if ("name".equals(bookInfo.getNodeName())) {
                        //获取相应节点数据
                        String name = bookInfo.getTextContent();
                        //获取name标签值
                        mTextView.append("书名:" + name + "\n");
                    } else if ("author".equals(bookInfo.getNodeName())) {
                        String author = bookInfo.getTextContent();
                        mTextView.append("作者:" + author + "\n\n");
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        }finally {
            inputStream.close();
        }
    }

不要忘记在main_activity.xml中添加个TextView哦!

8.2 、SAX解析

  • SAX(Simple API for XML),基于事件流驱动的XML解析方法。
  • SAX解析,主要是实现自己的Handler接口(DefaultHandler)。
  • 不可以主动控制处理事件的结束。
  • 解析代码如下:
public void getSAXData() {
            
        try {
            //第一步,创建SAX解析工厂
            SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
            //第二步,SAX工厂生产创建SAX解析器
            SAXParser saxParser = saxParserFactory.newSAXParser();
            //第三步,创建SAX文档处理者
            MyXMLHandler myXMLHandler = new MyXMLHandler();
            //第四步,获取xml流
            InputStream inputStream = this.getAssets().open("xmlTest.xml");
            //第五步,解析
            saxParser.parse(inputStream, myXMLHandler);
            inputStream.close();
            //第六步,获取解析完的数据
            ArrayList<Book> books = myXMLHandler.getBooks();
            for (int i = 0; i < books.size(); i++) {
                mTextView.append(books.get(i).getId());
                mTextView.append(".");
                mTextView.append("书名:"+books.get(i).getName());
                mTextView.append("\n");
                mTextView.append("作者:"+books.get(i).getAuthor());
                mTextView.append("\n\n");
            }
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

8.3、PULL解析

  • PULL(),同SAX基于事件流的一种XML解析方式。
  • 可以主动控制事件的结束。
  • 具体解析过程如下:
private void getPULLData() {
        List<Book> books = null;
        Book book = null;
        try {
            //第一步,获取解析器
            XmlPullParser parser = Xml.newPullParser();
            //第二步,获取数据
            InputStream inputStream = this.getAssets().open("xmlTest.xml");
            parser.setInput(inputStream, "UTF-8");
            //第三步,获取标识类型
            int type = parser.getEventType();
            //如果等于结束标识,停止解析
            while (type != XmlPullParser.END_DOCUMENT) {
                switch (type) {
                    //文档开始事件  
                    case XmlPullParser.START_DOCUMENT:
                        //初始化books列表  
                        books = new ArrayList<Book>();
                        break;
                    //解析开始事件  
                    case XmlPullParser.START_TAG:
                        //判断标签元素是否是book 
                        if ("book".equals(parser.getName())) {
                            book = new Book();
                            //得到book标签的属性值,并设置book的id
                            book.setId(parser.getAttributeValue(0));
                        }
                        if (book != null) {
                            //判断标签元素是否是name
                            if ("name".equals(parser.getName())) {
                                book.setName(parser.nextText());
                                //判断开始标签元素是否是author
                            } else if ("author".equals(parser.getName())) {
                                book.setAuthor(parser.nextText());
                            }
                        }
                        break;
                    //结束事件
                    case XmlPullParser.END_TAG:
                        if ("book".equals(parser.getName())) {
                            //将book添加到books集合
                            books.add(book);
                            book = null;
                        }
                        break;
                    default:
                }
                //下一个元素并触发相应事件
                type = parser.next();
            }//end while  
            inputStream.close();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < books.size(); i++) {
            mTextView.append(books.get(i).getId());
            mTextView.append(".");
            mTextView.append("书名:" + books.get(i).getName());
            mTextView.append("\n");
            mTextView.append("作者:" + books.get(i).getAuthor());
            mTextView.append("\n\n");
        }
    }

  • 完整的Activity代码:
package com.easy.xmltest;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Xml;
import android.widget.TextView;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class MainActivity extends AppCompatActivity {

    private TextView mTextView;
    private Book book;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = findViewById(R.id.text);
        //try {
        //    getXMLData();
        //} catch (IOException e) {
        //    e.printStackTrace();
        //}
        //getSAXData();
        getPULLData();
    }

    private void getPULLData() {
        List<Book> books = null;
        Book book = null;
        try {
            //第一步,获取解析器
            XmlPullParser parser = Xml.newPullParser();
            //第二步,获取数据
            InputStream inputStream = this.getAssets().open("xmlTest.xml");
            parser.setInput(inputStream, "UTF-8");
            //第三步,获取标识类型
            int type = parser.getEventType();
            //如果等于结束标识,停止解析
            while (type != XmlPullParser.END_DOCUMENT) {
                switch (type) {
                    //文档开始事件  
                    case XmlPullParser.START_DOCUMENT:
                        //初始化books列表  
                        books = new ArrayList<Book>();
                        break;
                    //解析开始事件  
                    case XmlPullParser.START_TAG:
                        //判断标签元素是否是book 
                        if ("book".equals(parser.getName())) {
                            book = new Book();
                            //得到book标签的属性值,并设置book的id
                            book.setId(parser.getAttributeValue(0));
                        }
                        if (book != null) {
                            //判断标签元素是否是name
                            if ("name".equals(parser.getName())) {
                                book.setName(parser.nextText());
                                //判断开始标签元素是否是author
                            } else if ("author".equals(parser.getName())) {
                                book.setAuthor(parser.nextText());
                            }
                        }
                        break;
                    //结束事件
                    case XmlPullParser.END_TAG:
                        if ("book".equals(parser.getName())) {
                            //将book添加到books集合
                            books.add(book);
                            book = null;
                        }
                        break;
                    default:
                }
                //下一个元素并触发相应事件
                type = parser.next();
            }//end while  
            inputStream.close();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < books.size(); i++) {
            mTextView.append(books.get(i).getId());
            mTextView.append(".");
            mTextView.append("书名:" + books.get(i).getName());
            mTextView.append("\n");
            mTextView.append("作者:" + books.get(i).getAuthor());
            mTextView.append("\n\n");
        }
    }

    public void getSAXData() {

        try {
            //第一步,创建SAX解析工厂
            SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
            //第二步,SAX工厂生产创建SAX解析器
            SAXParser saxParser = saxParserFactory.newSAXParser();
            //第三步,创建SAX文档处理者
            MyXMLHandler myXMLHandler = new MyXMLHandler();
            //第四步,获取xml流
            InputStream inputStream = this.getAssets().open("xmlTest.xml");
            //第五步,解析
            saxParser.parse(inputStream, myXMLHandler);
            inputStream.close();
            //第六步,获取解析完的数据
            ArrayList<Book> books = myXMLHandler.getBooks();
            for (int i = 0; i < books.size(); i++) {
                mTextView.append(books.get(i).getId());
                mTextView.append(".");
                mTextView.append("书名:" + books.get(i).getName());
                mTextView.append("\n");
                mTextView.append("作者:" + books.get(i).getAuthor());
                mTextView.append("\n\n");
            }
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void getXMLData() throws IOException {
        InputStream inputStream = null;
        try {
            inputStream = this.getAssets().open("xmlTest.xml");
            //第一步,创建DocumentBuilderFactory工厂对象
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            //第二步,通过工厂对象创建DocumentBuilder建造者
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            //第三步,创建Document存放整个xml的数据
            Document document = documentBuilder.parse(inputStream);
            //第四步,获取xml根节点
            Element element = document.getDocumentElement();
            //第五步,使用根节点和子节点名称获取所有子节点为‘book’的节点
            NodeList bookList = element.getElementsByTagName("book");


            //第一种方式通过Element和具体标签名获取值
            for (int i = 0; i < bookList.getLength(); i++) {
                //获取某个book标签元素
                Element book = (Element) bookList.item(i);
                //获取标签的id属性,并显示到TextView上
                mTextView.append(book.getAttribute("id"));
                //更具标签名获取name标签信息
                NodeList bookName = book.getElementsByTagName("name");
                //因为name没有子节点了所以省略了遍历直接取了第一个值,拿到name节点
                Node item = bookName.item(0);
                //获取name值并显示到TextView上
                mTextView.append("书名:" + item.getTextContent() + "\n");

                NodeList author = book.getElementsByTagName("author");
                Node authorItem = author.item(0);
                mTextView.append("作者:" + authorItem.getTextContent() + "\n\n");
            }
            //添加分隔线
            mTextView.append("\n --------------------------------------------------\n\n");

            //第二种方式通过Node节点获取值
            for (int i = 0; i < bookList.getLength(); i++) {
                //获取某个book标签节点
                Node book = bookList.item(i);
                //获取标签的属性列表,并显示到TextView上
                NamedNodeMap attributes = book.getAttributes();
                Node id = attributes.getNamedItem("id");
                mTextView.append(id.getTextContent());
                //获取book节点的子节点
                NodeList bookInfos = book.getChildNodes();
                for (int j = 0; j < bookInfos.getLength(); j++) {
                    //获取某个子节点
                    Node bookInfo = bookInfos.item(j);
                    //判断节点名
                    if ("name".equals(bookInfo.getNodeName())) {
                        //获取相应节点数据
                        String name = bookInfo.getTextContent();
                        //获取name标签值
                        mTextView.append("书名:" + name + "\n");
                    } else if ("author".equals(bookInfo.getNodeName())) {
                        String author = bookInfo.getTextContent();
                        mTextView.append("作者:" + author + "\n\n");
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } finally {
            inputStream.close();
        }
    }
}

8.4、三种解析对比

解析方式原理优点缺点使用场景
DOM解析基于树形结构,基于文档驱动,需要提前把文档缓存到内存中1.耗内存,因为需要提前保存到内存中,所以比较消耗内存。2.耗时间,解析前需要先把文档解析成树形结构所以比较耗时间耗内存,耗时间1.XML文档小。2.操作文档频繁。3.可能会修改xml
SAX解析基于事件流驱动,按需解析1.速度快,从开始往下解析,遇到相应的开始标签或者结束标签直接就可以返回当前的值,不需要全部解析完再取值。2.灵活性高,可以根据API灵活解析。3.占用内存少。1.解析复杂,API复杂。2.扩展性差,不能更改XML1.XML文档大。2.不需要修改文档。3.不需要多次访问文档。不需要控制事件停止时机。
PULL解析基于事件流驱动,按需解析1.速度快,从开始往下解析,遇到相应的开始标签或者结束标签直接就可以返回当前的值,不需要全部解析完再取值。2.灵活性高,可以根据API灵活解析。3.占用内存少。4.可控制事件结束的时机,比SAX更简单。扩展性差,不能更改XML1.解析复杂,API复杂。2.扩展性差,不能更改XML
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值