XML
1.什么是XML?
XML:extensiable markup language 被称作可扩展标记语言。
XML简单的历史介绍:
gml->sgml->html->xml
gml(通用标记语言)–在不同的机器进行通信的数据规范
sgml(标准通用标记语言)
html(超文本标记语言)
2.XML的用途
(1)配置文件
例子:Tomcat的web.xml,server.xml……,XML能够非常清晰描述出程序之间的关系。
(2)程序间数据的传输
XML的格式是通用的,能够减少交换数据时的复杂性。
(3)充当小型数据库
如果我们的数据有时候需要人工配置的,那么XML充当小型的数据库是个不错的选择,程序直接读取XML文件显然要比读取数据库要快。
HTML与表妹XML的区别?
XML 不是 HTML 的替代,XML 和 HTML 为不同的目的而设计:
XML 被设计为传输和存储数据,其焦点是数据的内容。
HTML 被设计用来显示数据,其焦点是数据的外观。
HTML 旨在显示信息,而 XML 旨在传输信息。
3.XML的技术架构
XML被设计为“什么都不做”,XML数据或XML文档只用于组织、存储数据,除此之外的数据生成、读取、传送、存取等等操作都与XML本身无关!
于是乎,想要操作XML,就需要用到XML之外的技术了:
为XML定规则:现在一般使用DTD或Schema技术,当然了Schema技术更为先进!
解析XML的数据:一般使用DOM或者SAX技术,各有各的优点
提供样式:XML一般用来存储数据的,但设计者野心很大,也想用来显示数据(但没人用XML来显示数据),就有了XSLT(eXtensiable Stylesheet Language Transformation)可扩展样式转换语言
4.XML语法
4.1.基本语法
(1)xml文档的后缀名 .xml
(2)xml第一行必须定义为文档声明
(3)xml文档中有且仅有一个根标签
(4)属性值必须使用引号(单双都可)引起来
(5)标签必须正确关闭
(6)xml标签名称区分大小写
4.2.快速入门
4.3.1.文档声明
(1)格式:<?xml 属性列表 ?>
version—版本号,必须的属性
encoding–编码方式。告知解析引擎当前文档使用的字符集,默认值ISO-8859-1
standalone–是否独立使用,默认是no。
如果是yes,则表示这个XML文档是独立的,不能引用外部的DTD规范文件(不依赖其他文件);
如果是no,则该XML文档不是独立的,表示可以引用外部的DTD规范文档(依赖其他文件)。
(2)XML声明放在XML的第一行
正确的文档声明格式,属性的位置不能改变!
4.3.2.指令(了解)
处理指令,简称PI(processing instruction)。
处理指令用来指挥解析引擎如何解析XML文档内容。
例如:
在XML文档中可以使用xml-stylesheet指令,通知XML解析引擎,应用css文件显示xml文档内容。
XML代码:
<?xml version="1.0" encoding="UTF-8" ?> <?xml-stylesheet type="text/css" href="1.css"?> 广州 深圳CSS代码:
guangzhou{
font-size: 40px;
}
4.3.3.标签
XML中元素和标签指的是同一个东西。
标签中需要值得注意的地方:
XML标签中的出现的空格和换行都会被当做标签内容进行处理
每个XML文档必须有且只有一个根标签
标签必须闭合
大小写敏感
不能交叉嵌套
不能以数字、符号开头
看起来好像有很多需要值得注意的地方,其实只需要记住:XML的语法是规范的!不要随意乱写!
标签命名规则:
名称可以包含字母、数字以及其他的字符
名称不能以数字或者标点符号开始
名称不能以字母 xml(或者 XML、Xml 等等)开始
名称不能包含空格
4.3.4.属性
属性是作为XML元素中的一部分的,命名规范也是和XML元素一样的!
(1)id属性值唯一
(2)属性值使用双引号
<中国 name=“china”></中国>
4.3.5.注释
注释和HTML的注释是一样的
4.3.6.CDATA
在编写XML文件时,有些内容可能不想让解析引擎解析执行,而是当作原始内容处理。遇到此种情况,可以把这些内容放在CDATA区里,对于CDATA区域内的内容,XML解析程序不会处理,而是直接原封不动的输出
语法:
4.3.7.转义字符
对于一些单个字符,若想显示其原始样式,也可以使用转义的形式予以处理。
转义符 符号
< <
> >
& &
" “
' ‘
5.XML文档约束
XML文档约束有两种:DTD和Schema。
5.1.DTD
DTD(Document Type Definition)——文档类型定义
作用:是定义XML文档的合法构建模块。
注:DTD就是个约束,用来约束XML的书写规范。
5.1.1.在XML中加入DTD声明
(1)内部声明: 即在XML文档中直接写约束。
(2)外部声明: 即引用外部DTD文件。
注:DTD约束外部文件的扩展名是.dtd。
5.1.2.DTD语法
(1)元素定义语法(即DTD对元素的限制)
基本语法:
元素类型:
EMPTY 表示该元素为空元素
(#PCDATA) 表示只有PCDATA的元素,不做延伸,放具体的数据
(e1,e2,e3……) 表示该元素下带有子元素,分别是e1,e2,注意顺序
ANY 表示没有任何内容的元素
(元素名) 表示只出现一次的元素
元素限制:
, 顺序
| 或
* 0次或多次
+ 1次或多次
? 0次或1次
(2)属性定义语法(即DTD对属性的限制)
基本语法:
<!ATTLIST 元素名称 属性名称1 属性类型 设置说明 属性名称2 属性类型 设置说明 …… >
属性类型:
CDATA 表示属性值为字符串
(男|女) “男” 表示只能填男或女,默认男
ID 值为唯一的id
ENTITY 表示实体(自学)
设置说明:
#REQUIRED 必须设置该属性
#IMPLIED 可以设置也可不设置
#FIXED 说明该属性的取值固定为一个值,需多测试
“默认值”
5.1.3.DTD示例
<?xml version="1.0" encoding="UTF-8"?><!ELEMENT person (name,sex,age,contact,br?)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ELEMENT contact (phone|email)>
<!ELEMENT phone (#PCDATA)>
<!ELEMENT email (#PCDATA)>
<!ELEMENT br EMPTY>
<!ATTLIST person
pid ID #REQUIRED
pname CDATA #IMPLIED
psex (男|女) "男"
>
]>
张三 男 22 13308082222李四 女 23 1234@qq.com
5.2.Schema
Schema是DTD的替代者,可描述XML文档的结构,也可作为XSD(XML Schame Definition)来引用。
Schema比DTD更强大,其最重要的能力之一就是对数据类型的支持。
5.2.1.简单案例
note.xml代码:
note.dtd代码:
<!ELEMENT note (to, from, heading, body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)>note.xsd代码:
<?xml version="1.0"?><xs:schema xmlns:xs=“http://www.w3.org/2001/XMLSchema”
targetNamespace=“http://www.w3school.com.cn”
xmlns=“http://www.w3school.com.cn”
elementFormDefault=“qualified”>
<xs:element name=“note”>
xs:complexType
xs:sequence
<xs:element name=“to” type=“xs:string”/>
<xs:element name=“from” type=“xs:string”/>
<xs:element name=“heading” type=“xs:string”/>
<xs:element name=“body” type=“xs:string”/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
5.2.2. 元素
元素是每一个 XML Schema 的根元素:
xs:schema
…
</xs:schema>
元素可包含属性。一个 schema 声明往往看上去类似这样:
<?xml version="1.0"?><xs:schema xmlns:xs=“http://www.w3.org/2001/XMLSchema”
targetNamespace=“http://www.w3school.com.cn”
xmlns=“http://www.w3school.com.cn”
elementFormDefault=“qualified”>
…
</xs:schema>
代码解释:
下面的片断:
xmlns:xs=“http://www.w3.org/2001/XMLSchema”
显示 schema 中用到的元素和数据类型来自命名空间 “http://www.w3.org/2001/XMLSchema”。同时它还规定了来自命名空间 “http://www.w3.org/2001/XMLSchema” 的元素和数据类型应该使用前缀 xs:
这个片断:
targetNamespace=“http://www.w3school.com.cn”
显示被此 schema 定义的元素 (note, to, from, heading, body) 来自命名空间: “http://www.w3school.com.cn”。
这个片断:
xmlns=“http://www.w3school.com.cn”
指出默认的命名空间是 “http://www.w3school.com.cn”。
这个片断:
elementFormDefault=“qualified”
指出任何 XML 实例文档所使用的且在此 schema 中声明过的元素必须被命名空间限定。
5.3.对.dtd的引用
<?xml version="1.0"?>5.4.对.xsd的引用
<?xml version="1.0"?><note
xmlns=“http://www.w3school.com.cn”
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation=“http://www.w3school.com.cn note.xsd”>
6.XML解析
XML解析就是操作xml文档,将文档中的数据读取到内存中。
6.1.操作XML文档
(1)解析(读取):将文档中的数据读取到内存中。
(2)写入:将内存中的数据保存到xml文档中。持久化的存储
6.2.XML解析方式
XML解析方式分为两种:
(1)DOM:Document Object Model文档对象模型
将标记语言文档一次性加载进内存,在内存中形成一颗dom树。
是W3C组织推荐解析XML的一种方式。
优点:操作方便,可以对文档进行CRUD的所有操作
缺点:占内存
(2)SAX:Simple API For XML
逐行读取,基于事件驱动的。它是XML社区的标准,几乎所有XML解析器都支持它。
优点:不占内存。
缺点:只能读取,不能增删改
6.3.常见解析器
(1)JAXP:sun公司提供的解析器,支持dom和sax两种思想。
(2)DOM4J:一款非常优秀的解析器。
(3)Jsoup:jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
(4)PULL:Android操作系统内置的解析器,sax方式的。
6.4.Jsoup
Jsoup 是一款Java的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
6.4.1.快读入门
操作步骤:
(1)导入jar包
jsoup-1.11.2.jar、JsoupXpath-0.3.2.jar
(2)获取Document对象
//获得路径
String path = XMLTest.class.getClassLoader().getResource(“student.xml”).getPath();
//获得Document对象
Document doc = Jsoup.parse(new File(path), “utf-8”);
(3)获取对应的标签Element对象
//获取元素
Elements elements = doc.getElementsByTag(“name”);
(4)获取数据
//获取数据
for (int i = 0; i < elements.size(); i++){
System.out.println(elements.get(i).text());
}
6.4.2.Jsoup对象的使用
(1)Jsoup:工具类,可以解析html或xml文档,返回Document。
parse:解析html或xml文档,返回Document
parse(File in, String charsetName):解析xml或html文件的。
parse(String html):解析xml或html字符串。
parse(URL url, int timeoutMillis):通过网络路径获取指定的html或xml的文档对象。
(2)Document:文档对象。代表内存中的dom树
获取Element对象方法:
getElementById(String id):根据id属性值获取唯一的element对象。
getElementsByTag(String tagName):根据标签名称获取元素对象集合。
getElementsByAttribute(String key):根据属性名称获取元素对象集合。
getElementsByAttributeValue(String key, String value):根据对应的属性名和属性值获取元素对象集合。
(3)Elements:元素Element对象的集合。可以当做 ArrayList来使用
(4)Element:元素对象
获取子元素对象方法:
getElementById(String id):根据id属性值获取唯一的element对象。
getElementsByTag(String tagName):根据标签名称获取元素对象集合。
getElementsByAttribute(String key):根据属性名称获取元素对象集合。
getElementsByAttributeValue(String key, String value):根据对应的属性名和属性值获取元素对象集合。
获取属性值的方法:
attr(String key):根据属性名称获取属性值
获取文本内容的方法:
text():获取文本内容
html():获取标签体的所有内容(包括字标签的字符串内容)
(5)Node:节点对象
Node是Document和Element的父类。
6.4.3.快捷查询方式
(1)selector:选择
使用的方法:
Elements select(String cssQuery)
参考代码:
//获得路径
path String path = JsoupTest.class.getClassLoader().getResource(“student.xml”).getPath();
//解析
Document document = Jsoup.parse(new File(path), “utf-8”);
//查询name标签
Elements elements = document.select(“name”); System.out.println(elements.get(0).text());
//查询id
Elements id = document.select("#cat"); System.out.println(elements.get(0).select(“name”).text());
//查找student中number等于heima_0001
Elements select = document.select(“student[number=“zhibang_0001”]”); System.out.println(select);
//查找student中number等于heima_0001中的age子标签
Elements select1 = document.select(“student[number=“zhibang_0001”]>age”); System.out.println(select1);
(2)XPath
说明:XPath即为XML路径语言,它是一种用来确定XML(标准通用标记语言的子集)文档中某部分位置的语言。
使用Jsoup的Xpath需要额外导入jar包:JsoupXpath-0.3.2.jar
参考代码:
//获得路径path
String path = JsoupTest.class.getClassLoader().getResource(“student.xml”).getPath();
//解析
Document document = Jsoup.parse(new File(path), “utf-8”);
//创建JXDocumnet对象
JXDocument jxDocument=new JXDocument(document);
//结合xpath语法查询
List jxNodes = jxDocument.selN("//student");
System.out.println(jxNodes);
List jxNode = jxDocument.selN("//student[@number=‘zhibang_0001’]");
System.out.println(jxNode);
6.5.dom4j + xpath 解析xml文件
xml解析一般分自带源生态的(效率低) ,另一种使用第三方读取解析(dom4j)。
6.5.1.dom4j
dom4j是java中一个优秀的开源框架,它提供了一组API用来解析xml文件。
优点:开源、轻量级、灵活、高性能、高效率、易维护。
常用于解析大型XML文档。
思想:将xml中所有元素(Element)称之为节点(Node),一个xml文件由N个节点组成。
DOM由节点组成:
Node分:元素节点(父)
属性节点(子)
文本节点(子)
方法:document.selectNodes(xpath); //查一组
document.selectSingleNode(xpath); //查单个
核心类:SAXReader
Document
6.5.2.Xpath
path等同数据库的select语句。
/ 定位路径 在系统中建一个文件叫document/students/student/sid|name
@ 属性
示例:
/students 获得students根节点
/students/student 获得students根节点下面所有的student节点
/students/student[@sid=‘s003’] 获得students根节点下面student节点中sid属性等于s003的节点
/students/student[@sid=‘s003’]/name 获得students根节点下面student节点中sid属性等于s003的节点下面的name节点
6.5.3.Dom4j + xpath案例:
//1. 加载xml文件
InputStream is = Demo2.class.getResourceAsStream("/students.xml");
SAXReader saxReader = new SAXReader();
//2. 转换成Document对象
Document document = saxReader.read(is);
//node节点、element元素,可直接将node转成element
//ListstudentNodes = (List)document.selectNodes("/students/student");
// 3. 获得指定元素路径下所有节点
List<Node> studentNodes = document.selectNodes("/students/student");
// 4. 遍历所有节点
for (Node studentNode : studentNodes) {
//将节点转换成元素
Element studentElement = (Element) studentNode;
// 获得元素中的sid属性值
// Attribute sidAttribute = studentElement.attribute("sid");
// 获得元素中属性的数据
// System.out.println(sidAttribute.getText());
// 获得元素中的sid属性值
String sid = studentElement.attributeValue("sid");
// 获得name的元素
Element nameElement = (Element) studentElement.selectSingleNode(“name”);
// 根据元素名获得数据
String name = nameElement.getText();
System.out.println(sid + “,” + name);
}
其他:
// sid=s003学生的姓名
String xpath = “/students/student[@sid=‘s003’]”;
Element e = (Element) document.selectSingleNode(xpath);
String name = e.selectSingleNode(“name”).getText();
System.out.println(name);
String xpath = “/students/student[@sid=‘s003’]/name”;
Element e = (Element) document.selectSingleNode(xpath);
System.out.println(e.getText());
6.6.XML解析操作
从上面的图很容易发现,应用程序不是直接对XML文档进行操作的,而是由XML解析器对XML文档进行分析,然后应用程序通过XML解析器所提供的DOM接口或者SAX接口对分析结果进行操作,从而间接地实现了对XML文档的访问!
常用的解析器和解析开发包的关系如下所示:
为什么有3种开发包?
jaxp开发包是JDK自带的,不需要导入开发包。
由于sun公司的jaxp不够完善,于是就被研发了Jdom。XML解析如果使用Jdom,需要导入开发包。
dom4j是由于Jdom的开发人员出现了分歧,dom4j由Jdom的一批开发人员所研发。XML解析如果使用Jdom,需要导入开发包【现在用dom4j是最多的!】。
6.6.1.jaxp
虽然jaxp解析XML的性能以及开发的简易度是没有dom4j好,但是jaxp不管怎么说都是JDK内置的开发包,我们是需要学习的!
DOM解析操作
DOM解析是一个基于对象的API,它把XML的内容加载到内存中,生成与XML文档内容对应的模型!当解析完成,内存中会生成与XML文档的结构与之对应的DOM对象树,这样就能够根据树的结构,以节点的形式对文档进行操作!
简单来说:DOM解析会把XML文档加载到内存中,生成DOM树的元素都是以对象的形式存在的!我们操作这些对象就能够操作XML文档了!
下面这样图就能很好地说明了,是怎么样生成与XML文档内容对应的DOM树!
<插图>
6.6.2.dom4j
dom4j是一个非常优秀的开源框架Java XML API,具有性能优异、功能强大和极易使用的特点。它提供了一组API用来解析xml文件。
优点:开源、轻量级、灵活、高性能、高效率、易维护。
注:dom4j常用于解析大型XML文档。
为什么需要有dom4j?
dom缺点:比较耗费内存。
sax缺点:只能对xml文件进行读取,不能修改、添加、删除。
dom4j:既可以提高效率,同时也可以进行crud操作。
因为dom4j不是sun公司的产品,所以我们开发dom4j需要导入开发包。
6.6.3.XPATH
什么是XPATH?
XPath 是一门在XML文档中查找信息的语言。
XPath 用于在 XML 文档中通过元素和属性进行导航。
为什么我们需要用到XPATH?
上面我们使用dom4j的时候,要获取某个节点,都是通过根节点开始,一层一层地往下寻找,这就有些麻烦了!
如果我们用到了XPATH这门语言,要获取得到XML的节点,就非常地方便了!
3.1
思想:将xml中所有元素(Element)称之为节点(Node),一个xml文件由N个节点组成。
DOM由节点组成:
Node分:元素节点(父)
属性节点(子)
文本节点(子)
方法:document.selectNodes(xpath); //查一组
document.selectSingleNode(xpath); //查单个
核心类:SAXReader
Document
3.2 xpath:path等同数据库的select语句。
/ 定位路径 在系统中建一个文件叫document/students/student/sid|name
@ 属性
示例:
/students 获得students根节点
/students/student 获得students根节点下面所有的student节点
/students/student[@sid='s003'] 获得students根节点下面student节点中sid属性等于s003的节点
/students/student[@sid='s003']/name 获得students根节点下面student节点中sid属性等于s003的节点下面的name节点
-
案例:
//1. 加载xml文件
InputStream is = Demo2.class.getResourceAsStream("/students.xml");
SAXReader saxReader = new SAXReader();
//2. 转换成Document对象
Document document = saxReader.read(is);//node节点、element元素,可直接将node转成element
//List studentNodes = (List)document.selectNodes("/students/student");// 3. 获得指定元素路径下所有节点
List studentNodes = document.selectNodes("/students/student");
// 4. 遍历所有节点
for (Node studentNode : studentNodes) {
//将节点转换成元素
Element studentElement = (Element) studentNode;// 获得元素中的sid属性值 // Attribute sidAttribute = studentElement.attribute("sid"); // 获得元素中属性的数据 // System.out.println(sidAttribute.getText()); // 获得元素中的sid属性值 String sid = studentElement.attributeValue("sid"); // 获得name的元素 Element nameElement = (Element) studentElement.selectSingleNode("name"); // 根据元素名获得数据 String name = nameElement.getText(); System.out.println(sid + "," + name);
}
// sid=s003学生的姓名
//String xpath = “/students/student[@sid=‘s003’]”;
//Element e = (Element) document.selectSingleNode(xpath);
//String name = e.selectSingleNode(“name”).getText();
//System.out.println(name);
String xpath = “/students/student[@sid=‘s003’]/name”;
Element e = (Element) document.selectSingleNode(xpath);
System.out.println(e.getText());
7.Jsoup
Jsoup是一款Java的Html解析器,可直接解析某个URL地址、HTML文本内容。
它提供了一套非常省力的API,可通过DOM、CSS以及类似于jQuery的操作方法来取出和操作数据。
8.XML建模
建模:通过java代码将xml中元素节点的主从关系描述出来。
以web.xml为例:
是否每次找web.xml中的数据都要读取一次web.xml。
实际是将web.xml中的数据读取出来转换成对象,每次访问调用对象。
案例:
<forward name="failed" path="/reg.jsp" redirect="false" />
<forward name="success" path="/login.jsp" redirect="true" />
分析:
-
将每个元素节点看作一个类,元素节点的属性就是类的属性,元素节点下的子元素节点就用集合来装。
创建一个模型类:ConfigModel、ActionModel、ForwardModel。ConfigModel中没有属性,只有0~N个ActionModel;
ActionModel中有属性path,type,还有0~N个ForwardModel;
ForwardModel中有属性name,path,redirect,没有子元素节点。
public class ConfigModel implements Serializable{
private Map<String, ActionModel> configMaps = new HashMap<String, ActionModel>();
//封装,重写get方法,put方法自己写
}public class ActionModel implements Serializable{
private String patht;
private String type;
private Map<String, ForwardModel> forwardMaps = new HashMap<String, ForwardModel>();
//封装,重写get/set方法,集合写put和get
}public class ForwardModel implements Serializable{
Map<String, String> configMaps = new HashMap<String, String>();
}注:一般类中放一个无参的构造方法。
写好后与xml对比下,写的这些类与xml结构是否匹配,缺什么补什么。
- 创建工厂类:ConfigModelFactory,用来生产ConfigModel。
工厂模式:私有化构造方法,创建静态代理方法。
操作步骤:
1.分析config.xml,根据元素,创建相应的 model 实体类
Forward类
Action类
Config类
-
为每个model实体类设置属性和set/get方法
注意:Action类中声明一个Map集合,并且将Forward对象的name做为Map集合的key,将Forward做为Map集合的value,然后再添加两个操作Map集合的方法:addForward(), getForward(),作用是可以从Map集合中添加Forward对象,和取出Forward对象。 -
创建工厂类
创建Config类的工厂类:ConfigFactory,用于实例化Config对象
通过dom4j+xpath去解析config.xml,将每个元素都实例化相应的对象,存入父级Map集合中 -
创建测试类
从Config从获得Map集合,遍历
再从Action中获得Map集合,遍历