1.XML
一、XML简单介绍
- XML全称是Extensible Markup Language
- 编写XML就是编写标签,与HTML非常类似,扩展名.xml
- 良好的人机可读性
XML与HTML的比较:
- XML与HTML非常相似,都是编写标签
- XML没有预定义标签,HMTL存在大量预定义标签
- XML重在保存与传输数据,HTML用于显示信息
XML的用途:
- JAVA程序的配置描述文件
- 用于保存程序产生的数据
- 网络间的数据传输
二、XML的文档结构
- 第一行必须是XML声明
- 有且只有一个根节点
- XML标签的书写规则与HTML完全相同
XML声明
XML声明说明XML文档的基本信息,包括版本号与字符集,写在XML第一行。
<?xml version="1.0" encoding="UTF-8"?>
version代表版本号1.0/1.1,encoding UTF-8设置字符集,用于支持中文
编写无误的XML可以被浏览器读取
XML标签允许嵌套
三、XML标签书写规则
1.合法的标签名
- 标签名要有意义
- 建议使用英文,小写字母,单词之间使用”-”分割
- 建议多级标签之间不要存在重名的情况
2.适当的注释与缩进
a.适当的注释与缩进可以让XML更容易阅读
注释:<!-- 注释 -->
3.合理使用属性
- 标签属性常用于描述标签不可或缺的信息
- 对标签分组或者为标签设置ID时常用属性表示
4.特殊字符与CDATA标签
标签体中,出现“<”、”>”特殊符号,会破坏文档结构
解决方案1:使用实体引用。
实体引用 | 对应符号 | 说明 |
< | < | 小于 |
> | > | 大于 |
& | & | 和号 |
' | ‘ | 单引号 |
" | “ | 双引号 |
解决方案2:使用CDATA标签。适用于出现大量特殊符号
- CDATA指的是不应由XML解析器进行解析的文本数据
- 从“<![CDATA["开始,到"]]>”结束
5.有序的子元素
在XML多层嵌套的子元素中,标签前后顺序应保持一致
四、XML语义约束
====XML文档结构正确,但可能不是有效的
例如,员工档案XML中绝不允许出现“植物品种”标签。XML语义约束就是用于规定XML文档中允许出现哪些元素。
====XML语义约束有两种定义方式:DTD与XML Schema
- DTD(Document Type Definition,文档类型定义)是一种简单易用的语义约束方式。
DTD文件的扩展名为.dtd
1.DTD定义节点:
利用DTD中<!ELEMENT>标签,我们可以定义XML文档中允许出现的节点及数量
以hr.xml为例:
- 定义hr节点下只允许出现1个employee节点。
<!ELEMENT hr (employee)>
- employee节点下必须包含以下四个节点,且按顺序出现。
<!ELEMENT employee (name,age,salary,department)>
- 定义name标签体只能是文本,"#PCDATA"代表文本元素
<!ELEMENT name(#PCDATA)>
2.DTD定义节点数量
如某个子节点需要多次重复出现,则需要在子节点后增加相应的描述符
- hr节点下最少出现1个employee子节点
<!ELEMENT hr (employee+)>
- hr节点下可出现0..n个employee子节点
<!ELEMENT hr (employee*)>
- hr节点下最多出现1个employee子节点
<!ELEMENT hr (employee?)>
3.XML引用DTD文件
在XML中使用<!DOCTYPE>标签引用DTD文件
书写格式:
<!DOCTYPE 根节点 SYSTEM "dtd文件路径">
示例:
<!DOCTYPE hr SYSTEM "hr.dtd">
4.实操,创建DTD文件并引用
注意:空格 <!ELEMENT hr (emoployee +)>
例:
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT hr (emoployee +)>
<!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标准。
例子:
hr.xsd文件如下:
<?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="999">
<complexType>
<sequence>
<element name="name" type="string"></element>
<element name="age" type="integer">
<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>
hr.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<hr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="hr.xsd">
<!-- 人力资源管理系统 -->
<!-- 根节点hr -->
<employee no="3309">
<name>张三</name>
<age>31</age>
<salary>4000</salary>
<department>
<dname>会计部</dname>
<address>xx大厦-B103</address>
</department>
</employee>
<employee no="3310">
<name>李四</name>
<age>34</age>
<salary>4500</salary>
<department>
<dname>工程部</dname>
<address>xx大厦-B104</address>
</department>
</employee>
</hr>
五、DOM文档对象模型
DOM(Document Object Model)定义了访问和操作XML文档的标准方法,DOM把XML文档作为树结构来查看,能够通过DOM树来读写所有元素。
对象模型,例:
文档:Document
根节点:cart
节点:item 节点:item
节点:name 节点:price 节点:name 节点:price
文本:空调 文本:2000 文本:面包 文本:10
属性:sn 属性:sn
Dom4j
- Dom4j是一个易用、开源的库,用于解析XML。它应用于Java平台,具有性能优异、功能强大和及其易于使用的特点。
- Dom4j将XML视为Document对象。
- Dom4j标签被Dom4j定义为Element对象。
利用Dom4j遍历XML
注意:先导入dom4j匝包
public class HrReader {
public void readXML() {
String file = "/Users/apple/eclipse-j2EE-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()用于获取节点文本
Attribute att=employee.attribute("no");
System.out.println("编号:"+att.getText());
String empName=name.getText();
System.out.println("姓名:"+empName);
System.out.println("年龄:"+employee.elementText("age"));
System.out.println("工资:"+employee.elementText("salary"));
Element department=employee.element("department");
System.out.println("部门:"+department.element("dname").getText());
System.out.println("地址:"+department.element("address").getText());
System.out.println("================");
}
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
HrReader read=new HrReader();
read.readXML();
}
}
利用Dom4j更新XML
public class HrWriter {
public void writerXML() {
String file = "/Users/apple/eclipse-j2EE-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("36");
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.writerXML();
}
}
六、XPath路径表达式
- XPath路径表达式是XML文档中查找数据的语言
- 掌握XPath可以极大的提高在提取数据时的开发效率
- 学习XPath本质就是掌握各种形式表达式的使用技巧
最常用的基本表达式
表达式 | 描述 |
nodename | 选取此节点的所有子节点 |
/ | 从根节点选取 |
// | 从匹配选择的当前节点选择文档中的节点 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
XPath基本表达式案例
路径表达式 | 结果 |
bookstore | 选取bookstore元素的所有子节点 |
/bookstore | 选取根元素bookstore 注释:假如路径起始于正斜杠(/),则此路径始终代表某元素的绝对路径 |
bookstore/book | 选取bookstore的子元素的所有book元素 |
//book | 选取所有book子元素,而不管它们在文档的位置 |
bookstore//book | 选择属性bookstore元素的后代的所有book元素,而不管它们位于bookstore之下的什么位置 |
//@lang | 选取名为lang的所有属性 |
XPath谓语表达式
路径表达式 | 结果 |
/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'] | 选取所有title元素,且这些元素拥有值为eng的lang属性 |
/bookstore/book[price>35.00] | 选取bookstore元素的所有book元素,且其中的price元素的值必须大于35.00 |
/bookstore/book[price>35.00]/title | 选取bookstore元素中的book元素的所有title元素,且其中的price元素的值必须大于35.00 |
XPath实验室
Jaxen介绍
- Jaxen是一个Java编写的开源的XPath库。这是适应多种不同的对象模型,包括DOM,XOM,Dom4j和JDOM
- Dom4j底层以来Jaxen实现XPath查询
- Jaxen下载地址:jaxen.codehaus.org
eclipse快捷键:command+1 /快速修正
例:
public class XPath {
public void XPath(String xpathExp) {
String file = "/Users/apple/eclipse-j2EE-workspace/xml/src/hr.xml";
SAXReader reader= new SAXReader();
try {
Document document=reader.read(file);
//document.selectNodes()该方法用来执行表达式的,返回查询到的节点
List<Node> nodes=document.selectNodes(xpathExp);
for(Node node:nodes) {
Element emp=(Element)node;
System.out.println(emp.attributeValue("no"));
System.out.println(emp.elementText("name"));
System.out.println(emp.elementText("age"));
System.out.println(emp.elementText("salary"));
System.out.println("===========================");
}
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
XPath tester=new XPath();
//实验室如下
//tester.XPath("/hr/employee");//获取所有员工信息
//tester.XPath("//employee");//获取所有员工信息
//tester.XPath("//employee[salary<4000]");//谓语表达式:获取工资小于4000的员工信息
//tester.XPath("//employee[name='李铁柱']");//谓语表达式:获取姓名为李铁柱的员工信息
//tester.XPath("//employee[@no=3310]");//谓语表达式:通过属性筛选工号为3304的员工信息
//tester.XPath("//employee[1]");//谓语表达式:第一个出现的员工信息,编号最小的
//tester.XPath("//employee[last()]");//谓语表达式:最后一个出现的员工
//tester.XPath("//employee[position()<6]");//范围筛选:6之前的员工信息
tester.XPath("//employee[1]| //employee[3]");//组合表达式,获取第1和第3的员工
}
}