二、Java框架基础02 XML

二、XML

2.1 XML 简介

XML 即可扩展标记语言,一种简单的数据存储语言,使用一系列简单的标记来描述结构化数据

XML 的特点

  • XML 与操作系统,编程语言的开发平台无关
  • 规范统一,实现不同系统之间的数据交互

2.1.1 XML 的文档结构

以下是 XML 代码描述图书的信息

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<books>
    <book id="bk101">
        <title>.NET高级编程</title>
        <author>王珊</author>
        <description>包含C#框架和网络编程等</description>
    </book>
    <book id="bk102">
        <title>XML基础编程</title>
        <author>李明明</author>
        <description>包含XML基础概念和基本用法</description>
    </book>
</books>
  • 通过以上代码来具体了解 XML 文档结构

2.1.2 XML 声明

  • <?xml version="1.0" encoding="UTF-8"?> 表示 XML 声明,用于标明这是一个 XML 文件
  • XML 声明主要有以下部分组成
    • version 文档符合 XML 1.0 规范
    • encoding 文档字符编码,默认为 UTF-8
  • 对于任何一个 XML 文档,都是固定格式

2.1.3 标签

  • XML 中,通过用尖括号 <> 括起来的各种标签来标记数据
  • 标签必须成对使用,必须有开始标签 <> 和 结束标签 </>
  • 标签之间是标签描述的内容
  • 例如 <author>王珊</author> 则表示作者信息

2.1.4 元素

  • XML 文档的主要部分是元素

  • 元素由开始标签、结束标签和元素内容注册

  • 元素内容指开始标签和结束标签之间的内容,可以包含子元素,字符数据等

  • 元素的命名规则如下

    • 名称中可以包含字母、数字或其他的字符
    • 名称不能以数字或标点符号开始
    • 名称不能以字符 xmlXML 等开始
    • 名称中不能包含空格
    • 元素允许是空元素,如 <title></title><title/>
  • 根元素

    • 每个 XML 文档必须有且仅有一个根元素,如 <books></books>
    • 根元素是一个完全包括文档中其他所有元素的元素
    • 根元素的起始标签要放在所有其他元素的起始标签之前
    • 根元素的结束标签要放在所有其他元素的结束标签之后
  • 属性

    • <book id="bk101"> 标签中使用 id 属性描述图书的编号信息
    • 属性的定义语法如下
    xml 复制代码
    <元素名 属性名="属性值">
    • 属性值用双引号包裹
    • 一个元素可以有多个属性,多个属性之间用空格隔开
    • 元素中不能直接包含 <"&
    • 属性只能加在元素的起始标签上
  • XML 中的特殊字符的处理

    • 在 XML 中,有时在元素的文本中会涉及一些特殊字符 < > ' " &
    • 使用这些字符,需要用到 XML 中的预定义实体代替
    • XML 中的预定义实体和特殊字符的对应关系
    特殊字符 实体名称
    < <
    > >
    & &amp;
    " &quot;
    ' '
  • CDATA - (未解析)字符数据

    • 术语 CDATA 是不应该由 XML 解析器解析的文本数据。

    • <& 字符在 XML 元素中都是非法的。

    • < 会产生错误,因为解析器会把该字符解释为新元素的开始。

    • & 会产生错误,因为解析器会把该字符解释为字符实体的开始。

    • CDATA 部分中的所有内容都会被解析器忽略

  • CDATA 语法格式如下

    xml 复制代码
    <![CDATA[要显示的字符]]>

2.2 解析 XML 概述

在实际应用当中,经常需要对 XML 文档进行各种操作

如在应用程序启动时去读取 XML 配置文件信息

或把数据库中的内容读取出来转为 XML 文档形式

这种情况就要运用到 XML 文档的解析技术

目前常用的 XML 解析技术有 4 种

2.2.1 DOM

  • DOM 是基于 XML 的树结构来完成解析的
  • DOM 解析 XML 文档时,会根据读取的文档,构建一个驻留内存的树结构
  • 使用 DOM API 可以操作这个树结构
  • 支持删除、修改、重新排列等多种功能
  • 但 DOM 解析同时也比较消耗资源

2.2.2 SAZ

  • SAZ 是基于事件的解析,为了解决 DMO 解析的资源消耗而出现的
  • SAZ 是通过事件处理器完成对文档的解析
  • SAZ 不用事先调入整个文档,所以它的优势就是占用资源少,内存消耗小
  • 在解析数据量较大的 XML 文档时会采用这种方式

2.2.3 JDOM

  • JDOM 是针对 Java 的特定文档模型
  • 它简化了与 XML 的交互并且币使用 DOM 更快
  • JDOM 仅使用具体类而不使用接口,在某方面简化了 API
  • 但是也限制了灵活性
  • API 大量使用了 Java 集合类型,对于属性这类的 Java 开发者而简化了使用

2.2.4 DOM4J

  • DOM4J 是一个非常优秀的 Java XML API
  • 具有性能优异、功能强大、易用的特点
  • DOM4J 用于在 Java 平台上使用 Java 集合框架处理 XML、XPath 和 XSLT
  • DOM4J 大量使用接口,面向接口编程使它币 JDOM 更加灵活

2.3 使用 DOM 读取 XML 数据

2.3.1 DOM 概念

  • DOM 即文档对象模型
  • DOM 把 XML 文件映射成一课倒挂的 "树"
  • 以根元素为根节点,每个节点都以对象形式存在
  • 通过存取这些对象就能存取 XML 文档的内容
  • 例如,创建文件 book.xml 并保存,book.xml 内容如下
xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<book id="bk101">
    <title>三国演义</title>
    <author>罗贯中</author>
    <price>30元</price>
</book>
  • book.xml 对应的 DOM 树结构

2.3.2 使用 DOM 读取手机收藏信息

  • 可以使用 JAXP 来解析 XML
  • JAXP 包含 3 个包,这 3 个包都在 JDK 中
    • org.w3c.dom:W3C 推荐的用于使用 DOM 解析 XML 文档的接口
    • org.xml.sax:用于使用 SAZ 解析 XML 文档的接口
    • javax.xml.parsers:解析其工厂工具,获得并配置特殊的解析器
  • 使用 DOM 解析 XML 时需要导入这些包中相关的类
  • JAXP 会把 XML 文档转换成一个 DOM 树
  • 使用 DOM 解析 XML 文档的步骤如下
    • 创建解析器工厂对象,即 DocumentBuilderFactory 对象
    • 由解析器工厂对象创建解析器对象,即 DocumentBuilder 对象
    • 由解析器对象对指定的 XML 文件进行解析,构建相应的 DOM 数,创建 Document 对象
    • 以 Document 对象为起点,对DOM 树的节点进行增加、删除、修改、查询等操作

2.3.3 使用 DOM 读取 XML 数据,使用 DOM 读取手机收藏信息中的品牌和型号信息 示例

XML 文档代码如下

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<PhoneInfo>
    <Brand name="华为">
        <Type name="P90"/>
    </Brand>
    <Brand>
        <Type name="iPhone Z"/>
        <Type name="iPhone ZL"/>
    </Brand>
</PhoneInfo>

手机收藏信息的 XML 文档对应的 DOM 树主要结构

根据使用 DOM 解析 XML 的文档步骤,关键代码如下

java 复制代码
package Test01;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;

public class Test01 {
    public static void main(String[] args) throws ParserConfigurationException, IOException, SAXException {
        //得到 DOM 解析器的工厂实例
        DocumentBuilderFactory dbf=DocumentBuilderFactory.newDefaultInstance();
        //从 DOM 工厂获取 DOM 解析器
        DocumentBuilder db=dbf.newDocumentBuilder();
        //解析 XML 文档,等到一个 Document 对象,即DOM数
        //xml 文件位置,从 src包下开始
        Document doc= db.parse("src/main/java/Test01/收藏信息.xml");
        //等到所有的 Brand 节点列表信息
        NodeList brandList=doc.getElementsByTagName("Brand");
        //循环 Brand 信息
        for (int i=0; i<brandList.getLength();i++){
        //获取第 i 个 Brand 元素信息
            Node brand=brandList.item(i);
        //获取第 i 个 Brand 元素的 name属性
            Element element= (Element) brand;
            String attrValue=element.getAttribute("name");
         //获取第 i 个 Brand 元素的所有子元素的 name 属性值
         NodeList types=element.getChildNodes();
            for (int j = 0; j <types.getLength() ; j++) {
                    Node node=types.item(j);
                    if (node.getNodeType()==Node.ELEMENT_NODE){
                        Element typeElement= ((Element) types.item(j));
                        String type=typeElement.getAttribute("name");
                        System.out.println("手机"+attrValue+type);
                    }
            }
        }
    }
}

2.3.4 使用 DOM 解析 XML 时主要使用以下对象

Node 对象

  • Node 对象是 DOM 结构中的基本对象,代表了文档树中的一个抽象节点
  • Node 对象的主要方法如下
方法名 说明
getChildNodes() 返回包含此节点所有子节点 NodeList
getFirstChild() 如果节点存在子节点,则返回第一个子节点
getLastChild() 如果节点存在子节点,则返回最后一个子节点
getNextSibling() 返回在 DOM 树中这个节点的下一个兄弟节点
getPreviousSibling() 返回在 DOM 树中这个节点的上一个兄弟节点
getNodeName() 返回节点的名称
getNodeValue() 返回节点的值
getNodeType() 返回节点的类型

NodeList 对象

  • NodeList 对象是指包含了一个或多个节点 (Node) 列表
  • 可以通过方法来获取列表中的元素
  • NodeList 对象的常用方法
方法名 说明
getLength() 返回列表长度
item(int idnex) 返回指定位置的 Node 对象

Document 对象

  • Document 对象代表整个 XML 文档
  • 所有其他的 Node 都以一定的顺序包含在 Document 对象之内
  • 它是对 XML 文档进行操作的起点,先通过解析 XML 源文件获取 Document 对象然后来执行后续的操作
  • Document 对象的主要方法
方法名 说明
getElementsByTagName(String name) 返回一个 NodeList 对象,包含所有给定标签名的标签
getDocumentElement() 返回一个代表这个 DOM 树的根节点的 Element 对象

Element 对象

  • Element 对象代表 XML了文档中的 标签元素
  • 在标签中可以包含属性,因而 Element 对象中也有存取属性的方法
  • Element 对象方法如下
方法名 说明
getAttribute(String attributename) 返回标签中给定属性名称的属性的值
getElementsByTagName(String name) 返回具有给定标签名称的所有后代 Elements 的 NodeList

注意事项

  • XML 文档中的空白符也会被作为对象映射在 DOM 树中
  • 所以直接调用 Node 对象的 getChildNodes() 方法有时会出现一些问题
  • 解决方案如下
    • 使用 Element 的 getElementByTagName(String name),返回的 NodeList 对象就是所期待的对象
    • 调用 Node 的 getChildNodes() 方法得到 NodeList 对象,每次通过 item() 方法提取 Node 对象然后判断
    • 判断 node.getNodeType()==Node.ELEMENT_NODE 即判断是否为元素节点

2.4 使用 DOM4J 解析 XML

2.4.1 DOM4J API 概述

  • 使用 DOM4J 只要了解 XML-DOM 模型就能使用
  • DOM4J 主要接口都在 org.dom4j 这个包里定义
说明
Attribute 定义了 XML 属性
Branch 为能够包含子节点的节点,定义了一个公共行为
CDATA 定义了 XML CDATA 区域
CharacterData 是一个标识接口,标识基于字符的节点,如 CDATA、Comment 和 Text
Comment 定义了 XML 注释的行为
Document 定义了 XML 文档
DocumentType 定义 XML DOCTYPE 声明
Element 定义了 XML 元素
ElementHandler 定义了 Element 对象的处理器
ElementPath 被 ElementHandler 使用,用于取得当前正在处理的路径层次信息
Entity 定义 XML 实体
Node 为 dom4j 中所有的 XML 节点定义了多态行为
NodeFilter 定义了在 dom4j 节点中产生的一个滤镜或谓词的行为
ProcessingInstruction 定义 XML 处理指令
Text 定义了 XML 文本节点
Visitor 用于实现 Visitor 模式
XPath 通过分析一个字符串提供一个 XPath 表达式
  • 使用这些需要提前导入一个 dom4j 的包
xml 复制代码
<!-- https://mvnrepository.com/artifact/org.dom4j/dom4j -->
<dependency>
    <groupId>org.dom4j</groupId>
    <artifactId>dom4j</artifactId>
    <version>2.1.4</version>
</dependency>

2.4.2 使用 DOM4J 操作 XML 数据

1、Document 对象相关

  • 读取 XML 文件,获得 Document 对象
java 复制代码
SAXReader reader=new SAXReader();
Document document=reader.read(new File("input.xml"));

2、节点相关

  • 获得文档的根元素
java 复制代码
Element rootElm=document.getRootElement();
  • 取得某节点的单个子节点
java 复制代码
Element memberElm=rootElm.element("member"); //member 是节点名
  • 取得节点的文字
java 复制代码
String text=emeberElm.getText();
//或者用下面这种方式
//取得根元素下的 name 子节点的文字
String text=rootElm.elementText("name");
  • 在某个节点下添加子节点,newMemberElm 是某个已存在的节点
java 复制代码
Element ageElm=newMemberElm.addELment("age");
  • 设置文字节点
java 复制代码
ageElm.setText("29");
  • 删除某节点
java 复制代码
parentElm.remove(childElm);// childElm 是待删除的节点,parentElm是其父节点

3、属性相关

  • 取得某节点下的某属性
java 复制代码
Element root=document.getRootElement();
Attribute attribute=toor.attribute("size"); //属性名 size
  • 取得属性的值
java 复制代码
String text=attribute.getText();
//也可以使用
String text2=root.element("name").attributeValue("firstname");
  • 为某节点添加属性
java 复制代码
newMemberElm.addAttribute("name","learningdom4j");
  • 设置属性的值
java 复制代码
Attribute attribute=root.attribute("name");
attribute.setText("learningdom4j");
  • 删除某属性
java 复制代码
Attribute attribute=root.attribute("size"); //属性名saize
root.remove(attribute)

e attribute=toor.attribute("size"); //属性名 size

- 取得属性的值

~~~java
String text=attribute.getText();
//也可以使用
String text2=root.element("name").attributeValue("firstname");
  • 为某节点添加属性
java 复制代码
newMemberElm.addAttribute("name","learningdom4j");
  • 设置属性的值
java 复制代码
Attribute attribute=root.attribute("name");
attribute.setText("learningdom4j");
  • 删除某属性
java 复制代码
Attribute attribute=root.attribute("size"); //属性名saize
root.remove(attribute)
相关推荐
brief of gali1 分钟前
记录一个奇怪的前端布局现象
前端
计算机毕设指导65 分钟前
基于 SpringBoot 的作业管理系统【附源码】
java·vue.js·spring boot·后端·mysql·spring·intellij-idea
Gu Gu Study6 分钟前
枚举与lambda表达式,枚举实现单例模式为什么是安全的,lambda表达式与函数式接口的小九九~
java·开发语言
Chris _data9 分钟前
二叉树oj题解析
java·数据结构
牙牙70514 分钟前
Centos7安装Jenkins脚本一键部署
java·servlet·jenkins
paopaokaka_luck22 分钟前
[371]基于springboot的高校实习管理系统
java·spring boot·后端
以后不吃煲仔饭35 分钟前
Java基础夯实——2.7 线程上下文切换
java·开发语言
进阶的架构师35 分钟前
2024年Java面试题及答案整理(1000+面试题附答案解析)
java·开发语言
The_Ticker41 分钟前
CFD平台如何接入实时行情源
java·大数据·数据库·人工智能·算法·区块链·软件工程
Json_181790144801 小时前
电商拍立淘按图搜索API接口系列,文档说明参考
前端·数据库