美文网首页
第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解析

    XML基础/XML解析 为什么要学XML XML是一种通用的数据交换格式 许多系统的配置文件都使用XML格式 xm...

  • 初识网络编程(第三篇)

    本篇博客的主要知识点是: 1 XML网络文件的解析 2 xml文件解析过程代码演示 3 在XML文件解析的基础上利...

  • xml序列化器及解析

    xml序列化器 得到xml文件的序列器 3.写xml文件 xml的解析 SAX DOM & DOM4 PULL解析...

  • 数据解析-XML解析

    今天来介绍一下XML数据解析的基础内容通俗的来讲 所谓XML数据解析就是将带有标签样式的数据 利用XML解析方法将...

  • iOS解析XML

    2.0 XML解析 2.1 XML简单介绍 (1) XML:可扩展标记语言 (2) XML解析 2.2 XML解析...

  • iOS开发-XML解析

    一、 XML解析 1.1 XML简单介绍 (1) XML:可扩展标记语言 (2) XML解析 1.2 XML解析 ...

  • 3-XML解析

    3.0 XML解析 3.1 XML简单介绍 (1) XML:可扩展标记语言 (2) XML解析 3.2 XML解析...

  • 三、XML Schema解析验证

    目录 1、XML解析2、XML Schema 或DTD3、复杂的解析和验证4、深度优先搜索 一、XML解析 有一个...

  • Android基础11

    网络基础: http方式访问网络 okhttp方式访问网络 pull方式解析xml数据 SAX方式解析xml数据5...

  • JSON与XML解析

    JSON与XML解析 json 待整理 xml 基础常识 原样输出内容: 约...

网友评论

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

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