XML(Extensible Markup Language)
XML可扩展标记语言,编写XML就是编写标签,与HTML非常类似,扩展名.xml。有良好的人机可读性
hr.xml
<employee>
<name>张三</name>
<age>31</age>
<height>178</height>
</employee>
- XML与HTML非常相似,都是编写标签
- XML没有预定义标签,HTML存在大量预定义标签
- XML重在保存与传输数据,HTML用于显示信息
XML用途
① 程序中有各种设置项提取出来存放在XML文件中,利用XML进行程序的设计
web.xml - web应用配置文件
<web-app>
<servlet>
<servlet-name>InitTest</servlet-name>
<servlet-class>moreservlets.InitServlet</servlet-class>
<init-param>
<param-name>param1</param-name>
<param-value>value1</param-value>
</init-param>
<init-param>
<param-name>param2</param-name>
<param-value>2</param-value>
</init-param>
</servlet>
</web-app>
② 用于保存程序产生的数据 [简单的变成可以把数据库导成xml]
hr.xml
<employee>
<name>张三</name>
<age>31</age>
<height>178</height>
<salary>7800</salary>
</employee>
③ 网络间的数据传输
webservice底层soap协议
<Envelop>
<Body>
<m:reversexmlns:m="urn:strings-com:IString">
<theString>Hello,World</theString>
</m:reversexmlns:m>
</Body>
</Envelop>
XML文档结构
第一行必须是XML声明
XML声明说明XML文档的基本信息,包括版本号与字符集,写在XML第一行
<?xml version="1.0" encoding="UTF-8"?> version代表版本号1.0 encoding UTF-8设置字符集,用于支持中文 <!-- 人力资源管理系统 --> <hr> <employee no="3309"> <name>张三</name> <age>31</age> <salary>4000</salary> <department> <dname>会计部</dname> <addresss>XX大厦-B103</addresss> </department> </employee> <employee no="3310"> <name>李四</name> <age>23</age> <salary>4000</salary> <department> <dname>工程部</dname> <addresss>XX大厦-B104</addresss> </department> </employee> </hr>
有且只有一个根节点
XML标签的书写规则与HTML相同
合法的标签名
标签名要有意义
建议使用英文,小写字母,单词之间使用”-“分割适当的注释与缩进
适当的注释与缩进可以让XML文档更容易阅读
合理使用属性
标签属性用于描述标签不可或缺的信息
对标签分组或者为标签设置Id时常用属性表示<shop-cart> <item sn="771938" category="电器"> <name>XXX空调</name> <price>2000.00</price> <num>1</num> </item> <item sn="890321" category="食品"> <name>法式面包</name> <price>10.00</price> <num>5</num> </item> </shop-cart>
特殊字符与CDATA标签
标签体中,出现”<”、”>”特殊字符,会破坏文档结构
错误的XML <question> 1+4<3是否正确?</question>
解决方案①:使用实体引用
实体引用 对应符号 说明 & It; < 小于 & gt; > 大于 & amp; & 和号 & apos; ‘ 单引号 & quot; “ 双引号 修改后的XML <question> 1+4<3是否正确?</question>
解决方案②:使用CDATA标签
CDATA指的是不应由XML解析器进行解析的文本数据
从”< ![CDATA[“开始,到”]] >“结束<lesson> <content> <![CDATA[ 本节我们来学习html中a标签的使用: <body> <a href="index.html">首页</a> </body> ]]> </content> </lesson>
有序的子元素
在XML多层嵌套的子元素中,标签前后顺序应保持一致
<…> </…>
XML语义约束之DTD
XML文档结构正确,但可能不是有效的
- 例如,员工档案XML中绝不允许出现 “植物品种” 标签。XML语义约束就是用于规定XML文档中允许出现哪些元素
- XML语义约束由两种定义方式:DTD与XML Schema
DTD(Document Type Definition, 文档类型定义) 是一种简单易用的语义约束方式
DTD文件的扩展名为.dtd [用于说明HTML中拥有哪些节点可以出现]
hr.dtd
<!ELEMENT hr (employee+)>
<!ELEMENT employee (name,age,salary,department)>
<!ATTLIST employee no CDATA "">
<!ELEMENT name (#PCDATA)>
...
定于hr节点下只允许出现1个employee子节点
<!ELEMENT hr (employee)>
employee节点下必须包含以下四个节点,且按顺序出现
<!ELEMENT employee (name,age,salary,department)
定义name标签体只能是文本,#PCDATA代表文本元素
<!ELEMENT name (#PCDATA)>
DTD定义节点数量
- 如果某个子节点需要多个重复出现,则需要在子节点后增加相应的描述符
[后面带个+号 最少出现一个]
hr节点下最少出现1个emploee子节点 [+]
<!ELEMENT hr (employee+)>
hr节点下可出现0..n个employee子节点 [*]
<!ELEMENT hr (employee*)>
hr节点下最多出现1个emploee子节点 [?]
<!ELEMENT hr (employee?)>
XML引用DTD文件
- 在XML中使用**< !DOCTYPE >**标签来引用DTD文件
书写格式:
<!DOCTYPE 根节点 SYSTEM "dtd文件路径">
示例:
<!DOCTYPE hr SYSTEM "hr.dtd">
案例 [XML像是描述 dtd像是约束 ]
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hr SYSTEM "hr.dtd">
<!-- 人力资源管理系统 -->
<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>23</age>
<salary>4000</salary>
<department>
<dname>工程部</dname>
<address>XX大厦-B104</address>
</department>
</employee>
</hr>
<?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)>
<!--里面是纯文本节点 department有两个子节点-->
XML Schema(比dtd更高级)
- XML Schema比DTD更为复杂,提供了多个功能
- XML Schema提供了数据类型、格式限定、数据范围等特性
- XML Schema是W3C标准
<?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>23</age>
<salary>4000</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">
<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="department">
<complexType>
<sequence>
<element name="dname" type="string"></element>
<element name="address" type="string"></element>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
</sequence>
<!--no在任何employee节点下必须存在-->
<attribute name="no" type="string" use="required"></attribute>
</complexType>
</element>
</schema>
DOM文档对象模型
DOM(Document Object Model)定义了访问和操作XML文件的标准方法,DOM把XML文档作为树结构来看,能够通过DOM树来读写所有元素。
Dom4j[以java的形式解析xml]
Dom4j是一个易用的、开源的库,用于解析XML。它应用于Java平台,具有性能优异、功能强大和极其易用的特点。
- Dom4j将XML视为Document对象
- XML标签被Dom4j定义为Element对象
Dom4j对xml的解析读取和遍历
[原则是按照documents根节点和子节点依次类推的顺序对其进行分析、解析、提取]
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 人力资源管理系统 -->
<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>23</age>
<salary>4000</salary>
<department>
<dname>工程部</dname>
<address>XX大厦-B104</address>
</department>
</employee>
</hr>
package src;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.util.List;
public class HrReader{
public void readXml() throws DocumentException {
String file = "D:\\JetBrains\\IdeaProjects\\Test_html\\src\\hr.xml";
//SAXReader类是读取XML文件的核心类,用于将XML解析后
SAXReader reader = new SAXReader();
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 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.elementText("dname"));
System.out.println(department.element("address").getText());
Attribute att = employee.attribute("no"); /*获取对应文本*/
System.out.println(att.getText());
System.out.println("====================");
}
}
public static void main(String[] args) throws DocumentException {
HrReader reader = new HrReader();
reader.readXml();
}
}
Dom4j更新(写入)XML
已追加写入的信息
<hr>
<employee no="3311">
<name>李铁柱</name>
<age>28</age>
<salary>3600</salary>
<department>
<dname>人事部</dname>
<address>XX大厦-B105</address>
</department>
</employee>
</hr>
package src;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
public class HrWriter {
public void weiteXml(){
String file = "D:\\JetBrains\\IdeaProjects\\Test_html\\src\\hr.xml";
SAXReader reader = new SAXReader();
try {
Document document = reader.read(file);
Element root = document.getRootElement();
//创建employee子节点 全新空子节点
Element employee = root.addElement("employee");
employee.addAttribute("no","3311");
Element name = employee.addElement("name");
name.setText("李铁柱");
employee.addElement("age").setText("28");
employee.addElement("salary").setText("3600");
Element department = employee.addElement("department");
department.addElement("dname").setText("人事部");
department.addElement("address").setText("XX大厦-B105");
//内存中组织的dom模型重新写入到对应文件中
Writer writer = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
document.write(writer);
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
HrWriter hrWriter = new HrWriter();
hrWriter.weiteXml();
}
}
XPath路径表达式
- XPath路径表达式是XML文档中查找数据的语言
- 掌握XPath可以极大的提高在读取数据时的开发效率
- 学习XPath本质就是掌握各种形式表达式的使用技巧
最常用的基本表达式
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点 |
/ | 从根节点选取 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
路径表达式 | 结果 |
---|---|
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[position()<3] | 选取最前面的两个属于bookstore元素的子元素的book元素 |
//title[@lang] | 选取所有拥有名为lang的属性的title元素 |
/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查询
<?xml version="1.0" encoding="UTF-8"?>
<!-- 人力资源管理系统 -->
<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>23</age>
<salary>3200</salary>
<department>
<dname>工程部</dname>
<address>XX大厦-B104</address>
</department>
</employee>
<employee no="3311">
<name>李铁柱</name>
<age>28</age>
<salary>3600</salary>
<department>
<dname>人事部</dname>
<address>XX大厦-B105</address>
</department>
</employee>
</hr>
package src;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import java.util.List;
public class XPathTestor {
public void xpath(String xpathExp){
String file = "D:\\JetBrains\\IdeaProjects\\Test_html\\src\\hr.xml";
SAXReader reader = new SAXReader();
try {
Document document = reader.read(file);
//执行xpath表达式 Node不仅查询标签还可以查询属性
List<Node> nodes = document.selectNodes(xpathExp);
for (Node node : nodes){
//转换成常用的Element对象 父类node强转
Element emp = (Element)node;
System.out.println(emp.attribute("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) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) {
XPathTestor testor = new XPathTestor();
//单斜杠要按照根目录一级一级搜索
// testor.xpath("/hr/employee");
//双斜杠 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
// testor.xpath("//employee");
// testor.xpath("//employee[salary<4000]");
// testor.xpath("//employee[name='李铁柱']");
// testor.xpath("//employee[@no=3309]");
// testor.xpath("//employee[1]");
// testor.xpath("//employee[last()]");
// testor.xpath("//employee[position()<6]"); 当前位置小于6
// testor.xpath("//employee[1] | //employee[3]");
}
}