跳至主要內容

XML

Yang大约 7 分钟

此文章根据 慕课网open in new window 视频课程总结,仅用于本人知识库记录

简介

XML 全称:EXtensible Markup Language,可扩展标记语言

  • 编写 XML 就是编写 标签,与 HTML 非常类似,***.xml
  • 有良好的人机可读性
  • XML 没有预定义标签,HTML 存在大量预定义标签
  • XML 重在保存与传输数据,HTML 用于显示信息

用途

  • Java 程序的配置描述文件

  • 用于保存程序产生的数据

  • 网络间的数据传输

文档结构

  • 第一行必须是 XML 声明 <?xml version="1.0" encoding="utf-8" ?>

    • version:版本号
      • 1.0:初始版本
      • 1.1:在初始版本上进行细节上的修改与升级
    • encoding:设置字符集
  • 有且只有一个根节点

  • XML 标签的书写规则与 HTML 相同

书写规则

合法的标签名

  • 标签名要有意义
  • 建议使用英文,小写字母,单词之间用 - 分割
  • 多级标签之间不要存在重名的情况

适当的注释与缩进

  • 提高文档可读性

合理使用属性

  • 常用与描述标签不可或缺的信息
  • 对标签分组或者为标签设置 ID 时常用属性表示

特殊字符与 CDATA 标签

  • 标签体中,出现 <> 特殊字符,会破坏文档结构

解决方案 1:使用实体引用:适用于特殊符号比较少的情况

符号说明实体引用
<小于&lt;
>大于&gt;
&和号&amp;
'单引号&apos;
"双引号&quot;

解决方式 2:使用 CDATA 标签

  • 用来表示不应由 XML 解析器进行解析的文本数据

  • 语法:<![CDATA[ 文本 ]]>

<lesson>
	<content>
  	<![CDATA[
   		<body>
				<a href="index.html">首页</a>
			</body>
    ]]>
  </content>
</lesson>

有序的子元素

  • 在 XML 多层嵌套的子元素中,标签前后顺序应保持一致

语义约束

  • XML 文档结构正确,但可能不是有效的
  • XML 予以约束就是用于规定 XML 文档中允许出现哪些元素

定义方式

DTD

  • 全称:Document Type Definition,文档类型定义

  • 是一种简单易用的语义约束方式

  • 以单独文件出现,扩展名:***.dtd

  • 用法

    • 使用 <!ELEMENT> 标签定义 XML 文档中允许出现的节点及数量
    • 使用 <ATTLIST> 标签定义 XML 文档中允许出现的属性
      • 书写格式:<!ATTLIST 元素名称 属性名称 属性类型 默认值>
    • 如某个子节点需要多次重复出现,则需要在子节点后增加响应的描述符
    • 在 XML 中使用 <!DOCTYPE> 标签来引用 DTD 文件
      • 书写格式:<!DOCTYPE 根节点 SYSTEM "dtd文件路径">
<!-- 定义 hr 节点下只允许出现 1 个 employee 子节点 -->
<!ELEMENT hr(employee)>

<!-- 定义 hr 节点下最少出现 1 个 employee 子节点 -->
<!ELEMENT hr(employee+)>

<!-- 定义 hr 节点下最多出现 1 个 employee 子节点 -->
<!ELEMENT hr(employee?)>

<!-- 定义 hr 节点下最少出现 0 个或多个 employee 子节点 -->
<!ELEMENT hr(employee*)>



<!-- employee 节点下必须包含以下四个节点,且按顺序出现 -->
<!ELEMENT employee(name,age,salary,department)>

<!-- employee 节点下需要有 no 属性,默认值为 "" -->
<!ATTLIST employee no CDATA "">

<!-- 定义 name 标签体只能是文本,#PCDATA 代表文本元素 -->
<!ELEMENT name(#PCDATA)>
...
<!-- hr.xml -->
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE hr SYSTEM "hr.dtd">

<hr>
    <employee no="3309">
        <name>张三</name>
        <age>30</age>
        <salary>4000</salary>
        <department>
            <dname>会计部</dname>
            <address>XX大厦-B103</address>
        </department>
    </employee>
    <employee no="3310">
        <name>李四</name>
        <age>23</age>
        <salary>3000</salary>
        <department>
            <dname>工程部</dname>
            <address>XX大厦-B103</address>
        </department>
    </employee>
</hr>
<!-- hr.dtd -->
<?xml version="1.0" encoding="utf-8" ?>
<!ELEMENT hr (employee+)>
<!ELEMENT employee (name,age,salary,department)>
<!ATTLIST employee no CDATA "">
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT salary (#PCDATA)>
<!ELEMENT department (dname,address)>
<!ELEMENT dname (#PCDATA)>
<!ELEMENT address (#PCDATA)>

XML Schema

  • 比 DTD 更为复杂,提供了更多功能
  • 提供了数据类型、格式限定、数据范围等特性
  • 是 W3C 标准
  • 文件后缀名:***.xsd
<?xml version="1.0" encoding="UTF-8"?>

<hr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="hr.xsd">
	<employee no="3309">
		<name>张三</name>
		<age>30</age>
		<salary>4000</salary>
		<department>
			<dname>会计部</dname>
			<address>XX大厦-B103</address>
		</department>
	</employee>
	<employee no="3310">
		<name>李四</name>
		<age>23</age>
		<salary>3000</salary>
		<department>
			<dname>工程部</dname>
			<address>XX大厦-B104</address>
		</department>
	</employee>
</hr>
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
	<element name="hr">
		<!-- complexType标签含义是复杂节点,包含子节点时必须使用这个标签 -->
		<complexType>
			<sequence>
				<element name="employee" minOccurs="1" maxOccurs="9999">
					<complexType>
						<sequence>
							<element name="name" type="string"></element>
							<element name="age">
								<simpleType>
									<restriction base="integer">
										<minInclusive value="18"></minInclusive>
										<maxInclusive value="60"></maxInclusive>
									</restriction>
								</simpleType>
							</element>
							<element name="salary" type="integer"></element>
							<element name="department">
								<complexType>
									<sequence>
										<element name="dname" type="string"></element>
										<element name="address" type="string"></element>
									</sequence>
								</complexType>
							</element>
						</sequence>
						<attribute name="no" type="string" use="required"></attribute>
					</complexType>
				</element>
			</sequence>
		</complexType>
	</element>
</schema>

DOM

文档对象模型(Document Object Model),定义了访问和操作 XML 文档的标准方法,DOM 把 XML 文档当做树结构来查看,能够通过 DOM 树来读写所有元素

Dom4j

一个易用的、开源的库,用于解析 XML,应用于 Java 平台,具有性能优异、功能强大和极易使用的特点

  • XML 视为 Document 对象
  • XML 标签 被 Dom4j 定义为 Element 对象

使用步骤

  • 新建 lib 文件夹
  • 将 Dom4j 拖入 lib 文件夹
  • 右键 Dom4j 包,点击 Build Path
读操作
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE hr SYSTEM "hr.dtd">

<hr>
    <employee no="3309">
        <name>张三</name>
        <age>30</age>
        <salary>4000</salary>
        <department>
            <dname>会计部</dname>
            <address>XX大厦-B103</address>
        </department>
    </employee>
    <employee no="3310">
        <name>李四</name>
        <age>23</age>
        <salary>3000</salary>
        <department>
            <dname>工程部</dname>
            <address>XX大厦-B103</address>
        </department>
    </employee>
</hr>
// Dom4j 读操作
// HrReader.java
package com.imooc.dom4j;

import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class HrReader {
	public void readXml() {
		String file = "/Users/sunzhenyang/eclipse-workspace/xml/src/hr.xml";
		// SAXReader类 是读取 XML 文件的核心类,用于将 XML 解析后以 “树” 的形式保存在内存中
		SAXReader reader = new SAXReader();

		try {
			Document document = reader.read(file);
			// 获取 XML 文档的根节点,即 hr 标签
			Element root = document.getRootElement();
			// elements 方法用于获取指定的标签集合
			List<Element> employees = root.elements("employee");
			for (Element employee : employees) {
				// element 方法用于获取唯一的子节点对象
				Element name = employee.element("name");
				// getText 方法用于获取标签文本
				String emName = name.getText();
				System.out.println(emName);

				System.out.println(employee.elementText("age"));
				System.out.println(employee.elementText("salary"));
				Element department = employee.element("department");
				System.out.println(department.elementText("dname"));
				System.out.println(department.elementText("address"));
				Attribute attr = employee.attribute("no");
				System.out.println(attr.getText());
			}
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		HrReader reader = new HrReader();
		reader.readXml();
	}
}
写操作
// Dom4j 写操作
// HrWriter.java.
package com.imooc.dom4j;

import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class HrWriter {
	public void writeXml() {
		String file = "/Users/sunzhenyang/eclipse-workspace/xml/src/hr.xml";
		SAXReader reader = new SAXReader();
		try {
			Document document = reader.read(file);
			Element root = document.getRootElement();
			Element employee = root.addElement("employee");
			employee.addAttribute("no", "3311");
			Element name = employee.addElement("name");
			name.setText("李铁柱");
			employee.addElement("age").setText("37");
			employee.addElement("salary").setText("3600");
			Element department = employee.addElement("department");
			department.addElement("dname").setText("人事部");
			department.addElement("address").setText("XX大厦-B105");
			Writer writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
			document.write(writer);
			writer.close();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static void main(String[] args) {
		HrWriter hrWriter = new HrWriter();
		hrWriter.writeXml();
	}
}

XPath 路径表达式

  • 是 XML 文档中查找数据的语言
  • 可以极大提高在提取数据时的开发效率
  • 学习 XPath 本质就是掌握各种形式表达式使用技巧

基本表达式

表达式描述
nodename选取子节点的所有子节点
/从根节点选取
//从匹配选择的当前节点选择文档中的节点,而不考虑他们的位置
.选取当前节点
..选取当前节点的父节点
@选取属性

谓语表达式

路径表达式结果
/bookstore/book[1]选取属于 bookstore 子元素的第一个 book 元素
/bookstore/book[last()]选取属于 bookstore 子元素的最后一个 book 元素
/bookstore/book[last()-1]选取属于 bookstore 子元素的倒数第二个 book 元素
/bookstore/book[position()<3]选取前两个属于 bookstore 元素的 book 子元素
//title[@lang]选取所有拥有 lang 属性的 title 元素
//title[@lang='eng']选取所有 lang 属性为 eng 的 title 元素
/bookstore/book[price>35.00]选取所有 bookstore 元素下的所有 price 元素值大于 35.00 的 book 元素
/bookstore/book[price>35.00]/title选取所有 bookstore 元素下所有 price 元素值大于 35.00 的 book 元素下的 title 元素

案例

路径表达式结果
bookstore选取 bookstore 元素的所有子节点
/bookstore选取根元素 bookstore,加入路径起始于正斜杠(/),则地路径始终代表到某元素的绝对路径
bookstore/book选取属于 bookstore 的子元素中的所有 book 元素
//book选取所有 book 子元素,而不管他们在文档中的位置
bookstore//book选取属于 bookstore 元素的后代中的所有 book 元素,而不管他们位于 bookstore 之下的什么位置
//@lang选取属性名为 lang 的所有元素
上次编辑于:
贡献者: sunzhenyang