美文网首页
第3讲.XML基础/XML解析

第3讲.XML基础/XML解析

作者: 祥祺 | 来源:发表于2020-03-18 08:35 被阅读0次

    XML基础/XML解析

    为什么要学XML

    XML是一种通用的数据交换格式

    许多系统的配置文件都使用XML格式

    xml可以跨平台,主流各种平台都对xml有支持, 真正的跨平台.

    xml 是各种应用程序之间进行数据传输的最常用的工具。

    掌握XML是软件开发人员的一项基本技能

    任意一个javaee框架中都要用到XML。

    XML结构清晰(树状结构),不仅让人能够明白,还让计算机也能够明白。

    XML作为一种公订的、开放的标准,不受知识产权的限制.(免费)

    具有结构性的数据应该使用xml来存取,这样看上去结构更加的清晰(如省市区的数据)

    XML是什么

    XML(eXtensible Markup Language),是一种可扩展的标记语言,类似HTML。如: <h1></h1>

    XML技术是W3C组织(World Wide Web Consortium万维网联盟)发布的,目前遵循的是W3C组织于1998年发布的XML1.0规范。

    XML被广泛认为是继Java之后在Internet上最激动人心的新技术。

    HTML: 显示页面,网页. 学习里面自带的标签<html>

    XML: 主要是用于描述配置信息。

    XML标签没有被预定义,需要用户自行定义标签。

    XML的语法

      1. 文档声明:

    在编写XML文档时,需要先使用文档声明来声明XML文档。且必须出现在文档的第一行。

    最简单的语法:

    如:<?xml version="1.0"?>
    

    用encoding属性说明文档所使用的字符编码,默认为UTF-8。

    如:<?xml version="1.0" encoding="UTF-8"?>
    

    用standalone属性说明文档是否独立,即是否依赖其他文档。yes表示独立文档不依赖,no表示要依赖,可以不写则表示可以依赖可以不依赖

    如:<?xml version="1.0" standalone="no"?>
    
      1. 编码:XML有两个编码: 保存在磁盘上的文件编码要与声明的编码一致。要保证两个编码相同,都为UTF-8

    内容编码:文档声明中指定

    文件本身的编码:文件另存为时可以选择

      1. 元素(标签)<>(可以自定义标签)

    XML文档必须有一个根元素.

    标签区分大小写的.<a> <A>
    
    有开始标签就必须有结束标签.<linkman></linkman> 或者 自闭合<linkman/>
    

    不允许标签交叉嵌套

      1. 属性:

    属性是元素的一部分,它必须出现在元素的开始标签中

    key=value格式,尽量在编写的时候 value 前后不要有空格

    属性的key不能使用空格,冒号特殊字符.

    属性的key需要以字母开头.

    属性的value必须使用引号或者双引号

    • 5.注释

        如:<!-- 注释 -->
      
    • 6.命名规则

    在XML中,可以使用自己需要的元素来扩展标记语言。

    命名基本规则:

    ·元素名称不能以数字或特殊字符开头
    
    ·可以包含字母,数字,下划线等
    
    ·不能以字符串“XML”作为开头
    
    ·不能包含空格
    
    ·尽量不要包含特殊字符
    
    ·区分大小写
    

    XML文件的约束(了解)

    为什么要有XML约束

    XML本身是可扩展的,用户可以写任意的标签,但是这样一来就可能乱套了,用户的随意会让XML表示的含义不再统一并且解析会变得困难,所以一个框架不应该让用户任意定义标签。我们需要有约束来规范XML可以出现哪些标签,不能出现哪些标签以及标签之间的顺序、出现的次数,标签有哪些属性等。

    我们编写XML文件的时候有约束的话还可以根据约束给我们提示该怎么写

    XML文件约束的分类

    xml 约束分两种: dtd 约束,schama 约束

    什么是DTD

    DTD(Document Type Definition),文档类型定义,用来约束XML文档。规定XML文档中元素的名称,子元素的名称及顺序,元素的属性等。

    一个xml文档中只能添加一个DTD约束

    DTD约束的语法

    元素声明

    定义元素语法:<!ELEMENT 元素名 元素描述>

    元素名:自定义
    元素描述包括:符号和数据类型

    常见符号:? * + () | ,
    常见类型:#PCDATA 表示内容是文档,不能是子标签
    
    1.png

    DTD用法

    2.png

    学习了dtd 约束 ,为何要还学习schema约束呢?

    因为dtd约束有局限性 :一个xml文档只能有一个dtd约束

    什么是Schema

    Schema是新的XML文档约束;

    Schema要比DTD强大很多,是DTD 替代者;

    Schema本身也是XML文档,但Schema文档的扩展名为xsd,而不是xml。

    Schema 功能更强大,数据类型更完善

    一个xml文档中可以添加多个schema约束

    为何支持多个schema 约束 就是因为 Schema 支持名称空间

    什么是命名空间

    如果一个XML文档中使用多个Schema文件,而这些Schema文件中定义了相同名称的元素时就会出现名字冲突。这就像一个Java文件中使用了import java.util.和import java.sql.时,在使用Date类时,那么就不明确Date是哪个包下的Date了。

    总之名称空间就是用来处理元素和属性的名称冲突问题,与Java中的包是同一用途。如果每个元素和属性都有自己的名称空间,那么就不会出现名字冲突问题,就像是每个类都有自己所在的包一样,那么类名就不会出现冲突。

    Schema语法

    3.png

    Schema用法

    4.png

    XML解析

    XML文档结构分析

    5.png

    开发中比较常见的解析方式

    有两种,如下:

    • A. DOM:要求解析器把整个XML文档装载到内存,并解析成一个Document对象。

      1. 优点:元素与元素之间保留结构关系,故可以进行增删改查操作。

      2. 缺点:XML文档过大,可能出现内存溢出显现。

    • B. SAX:是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。并以事件驱动的方式进行具体解析,每执行一行,都将触发对应的事件。(了解)

      1. 优点:处理速度快,可以处理大文件

      2. 缺点:只能读,逐行后将释放资源。

    获取Document对象

    要操作XML,先就得有Document对象:

    把一个XML文件加载进内存的时候,在内存中形成所谓的一种树状结构,我们把这一个结构称之dom树,创建的对象叫Document对象.

    注意:

    我们在Java代码中所做的增/删/改/查操作,都仅仅是操作的是内存中的Document对象,和磁盘中的XML文件没有关系.如图:

    6.png

    比如:删除一个联系人信息之后,XML文件中数据依然存在,此时出现内存中的数据和磁盘文件中的数据不同步,所以,对于增删改操作,我们需要做同步操作(把内存中的数据和磁盘的XML文件数据保持一致).

    DOM:在第一次的时候就会把XML文件加载进内存,如果XML文件过大,可能会造成内存的溢出.

    DOM:在做增删改查操作的时候比较简单,但是性能却不高(线性搜索).

    // 首先要获取Document对象,如何获取呢?

    前提是必须有 xml文件

    File file = new File("C:/stsworkspace/day03/contacts.xml");
    

    注意:
    当导入类/接口的时候,导入的包是org.w3c.dom ,因为xml遵循的是w3c组织的规范

    思路:

    1.获取一个DocumentBuilderFactory工厂对象
    
    通过DocumentBuilderFactory调用newInstance 方法来获取工厂对象  DocumentBuilderFactory.newInstance();
    
    2.获取DocumentBuilder对象
    
    通过工厂对象调用newDocumentBuilder方法来获取  :工厂对象.newDocumentBuilder() 
    
    3.通过documentBuilder对象,获取document对象
    
    获取的方式有两种:当xml文件不存在的时候,可以调用newDocument方法来创建一个Document对象
    当xml文件存在的情况,可以调用parse方法来从xml文件中解析得到一个Document对象
    

    如图:


    7.png

    DOM中常用的API

    Node接口:

    String getTextContent():获取元素的文本内容
    void setTextContent(String textContent):给元素设置新的文本内容
    Node appendChild(Node newChild):往当前元素中增加新的儿子.
    老爸.appendChild(新的儿子);
    
    Node removeChild(Node oldChild):从当前节点下删除指定的儿子节点.
    

    Document接口:

        Element getDocumentElement():获取并返回文档的根元素对象.
        Element getElementById(String elementId):根据指定的id属性的值,获取对应的Element对象.
        
        若当前解析的XML文件没有约束文件,并且没有对id属性有ID类型约束,则不能使用该方法.
        NodeList getElementsByTagName(String tagName):根据指定的标签名获取文档中所有的子元素.
        Element createElement(String tagName):根据指定的元素名,创建Element对象.
    

    Element接口:

        NodeList getElementsByTagName(String tagName):根据指定的标签名获取当前元素下(this)所有的子元素.
        void setAttribute(String attrName, String attrValue):为当前元素对象设置指定名子的属性和属性值.
        String getAttribute(String attrName):获取当前元素指定属性名的属性值.
    

    DOM操作练习

    需求:得到某个具体的文本节点的内容:取出第二个联系人的名字

    //  需求:获取第二个联系人的姓名
    @Test
    public void testQuery() throws Exception {
            // 1. 获取document对象
            Document document = DocumentBuilderFactory.newInstance()//获取工厂对象
                    .newDocumentBuilder() //获取构建器
                    .parse(file);
            // 2. 获取文档中的根元素contacts
            Element root = document.getDocumentElement();
            // 3. 获取contacts根元素下面的第二个子元素 linkman
            Element linkmanEle = (Element) root.getElementsByTagName("linkman").item(1);
            // 4. 获取linkman元素下面的子元素name
            Node nameEle = linkmanEle.getElementsByTagName("name").item(0);
            // 5. 获取name元素对应的文本内容
            String content = nameEle.getTextContent();
            System.out.println(content);
        }
        
    

    需求:修改某个元素节点的主体内容:第一个联系人的姓名为“马云”

    //  需求:修改第一个联系人的姓名为“马云”
        @Test
        public void testUpdate() throws Exception {
            // 1. 获取document对象
            Document document = DocumentBuilderFactory.newInstance()//获取工厂对象
                    .newDocumentBuilder() //获取构建器
                    .parse(file);
            // 2. 获取文档中的根元素contacts
            Element root = document.getDocumentElement();
            // 3. 获取contacts根元素下面的第二个子元素 linkman
            Element linkmanEle = (Element) root.getElementsByTagName("linkman").item(0);
            // 4. 获取linkman元素下面的子元素name
            Node nameEle = linkmanEle.getElementsByTagName("name").item(0);
            //5. 修改name元素对应的文本内容
            nameEle.setTextContent("马云");
            //6. 同步数据:把内存中的数据同步到磁盘上 使用的核心类: Transformer
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.transform(new DOMSource(document), new StreamResult(file));
        }
    

    如图:

    8.png

    需求:向指定元素节点中增加子元素节点:增加一个联系人信息

    //  需求:往xml中新增一个新的联系人
        @Test
        public void testAdd() throws Exception {
            // 1. 获取document对象
            Document document = DocumentBuilderFactory.newInstance()//获取工厂对象
                    .newDocumentBuilder() //获取构建器
                    .parse(file);
            // 2. 获取文档中的根元素contacts
            Element root = document.getDocumentElement();
            // 3. 创建元素(linkman,name,address,group)
            Element linkmanEle = document.createElement("linkman");
            Element nameEle = document.createElement("name");
            Element addressEle = document.createElement("address");
            Element groupEle = document.createElement("group");
            // 4.  给上面创建的元素设置文本内容
            linkmanEle.setAttribute("id", "3");
            nameEle.setTextContent("李清照");
            addressEle.setTextContent("上海青浦区");
            groupEle.setTextContent("叩丁狼教育");
            // 5.  把元素name,address ,group 设置到linkman中
            linkmanEle.appendChild(nameEle);
            linkmanEle.appendChild(addressEle);
            linkmanEle.appendChild(groupEle);
            // 6.  把linkman元素设置到contacts中
            root.appendChild(linkmanEle);
            // 7.  同步数据:把内存中的数据同步到磁盘上
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.transform(new DOMSource(document), new StreamResult(file));
        }
        
    

    需求:操作XML文件属性:设置/获取联系人的id属性

    //  需求:设置/获取第一个联系人的id属性值为10
        @Test
        public void testDelete() throws Exception {
            // 1. 获取document对象
            Document document = DocumentBuilderFactory.newInstance()//获取工厂对象
                    .newDocumentBuilder() //获取构建器
                    .parse(file);
            // 2. 获取文档中的根元素contacts
            Element root = document.getDocumentElement();
            // 3. 获取contacts根元素下面的第一个子元素 linkman
            Element linkmanEle = (Element) root.getElementsByTagName("linkman").item(0);
            // 4. 设置属性的值为10
             linkmanEle.setAttribute("id",10);
            // 5. 获取属性的值
             System.out.println("id的值为:" +linkmanEle.getAttribute("id") );  
            //6. 同步数据:把内存中的数据同步到磁盘上 使用的核心类: Transformer
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.transform(new DOMSource(document), new StreamResult(file));
    
        }
    }
    
    

    需求:删除指定元素节点:删除第三个联系人信息

    //  需求:删除第三个联系人信息
        @Test
        public void testDelete() throws Exception {
            // 1. 获取document对象
            Document document = DocumentBuilderFactory.newInstance()//获取工厂对象
                    .newDocumentBuilder() //获取构建器
                    .parse(file);
            // 2. 获取文档中的根元素contacts
            Element root = document.getDocumentElement();
            // 3. 获取contacts根元素下面的第三个子元素 linkman
            Element linkmanEle = (Element) root.getElementsByTagName("linkman").item(2);
            // 4. 删除第三个联系人信息
            root.removeChild(linkmanEle);
            //方式二:linkmanEle.getParentNode().removeChild(linkmanEle);
            //6. 同步数据:把内存中的数据同步到磁盘上 使用的核心类: Transformer
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.transform(new DOMSource(document), new StreamResult(file));
    
        }
    }
    

    相关文章

      网友评论

          本文标题:第3讲.XML基础/XML解析

          本文链接:https://www.haomeiwen.com/subject/ftymyqtx.html