java回顾之XML和dom4j
1.XML
1.XML介绍
XML 指可扩展标记语言(EXtensible Markup Language)。
XML是用来传输数据的,不是用来显示数据的。之后学习另外一个HTML是用来显示数据的。
XML中没有预定义标签,所有的标签都是自己定义的。
XML是W3C的一个语言。
W3C在1988年2月发布XML1.0版本,我们现在用的就是1.0版本。在后面也有新的版本,但是新版本不太兼容旧版本,所以新版本没有被推广开。
2.编写XML
XML不是java的内容,之前的java文件都需要写在src里面,XML不需要写在src里面
person.xml
<person>
<name>柳岩</name>
<age>36</age>
</person>
3.XML的作用
-
用来【存储数据】,作为数据交互的载体,可以传输数据
-
可以作为【配置文件】,在框架中会有使用
4.XML的组成部分
-
文档声明
<?xml version="1.0" encoding="UTF-8" ?>
-
注意事项:
1.文档声明必须以<?xml开头 , 必须以?>结尾
2.文档声明必须写在第一行第一列
3.version表示版本,encoding表示编码
4.文档声明可以不写
-
-
元素
-
元素是XML中最重要的组成部分,元素也叫标签
-
标签分为开始标签和结束标签,开始标签<名字> 结束标签</名字>
-
开始标签和结束标签中间写的是标签内容,标签的内容可以是文本,也可以是其他标签
-
如果标签没有任何内容,那么可以定义为 自闭合标签(比如:<名字/>)
-
命名规则: 不要使用XML xML xml 写样的单词
不能使用空格,冒号
命名区分大小写
-
一个XML文件只有一个根标签
-
-
属性
-
属性是标签的一部分,属性必须写在开始标签或写在自闭合标签中,不能写在结束标签中
-
属性的书写格式:属性名=属性值,属性值必须使用单引号或双引号括起来,在XML中,单引和双引是没区别的。
-
一个元素可以有任意个属性,但是属性之间不能重名,多个属性之间用空格隔开
-
属性名不能使用特殊字符,必须以字母开头
-
-
注释
-
对代码的解释说明
<!--这是一个标签-->
快捷键: ctrl + / -
-
转义字符
有些特殊的字符在XML中是会被识别的,比如<在XML中会被识别为标签,如果想要写这样的符号,需要用转义字符.
< <
> >
" "
' '
& &<说说>不要低头,皇冠<会掉></说说>
-
CDATA区 (了解)
如果有大量的转义字符,可能就降低代码的阅读性,所以可以使用CDATA区去代替转义字符,在CDATA区中的文本不会被识别为特殊符号。
<![CDATA[
文本数据
]]>
2.约束
1.概念
因为XML本身没有预定义标签,可能大家写的XML就会乱七八糟。
约束的作用就是限制XML里面可以写什么。
约束有两种: DTD约束 和 Schema约束。
约束是不会让我们写的,我们是根据约束去写对应的XML!!!
2.DTD约束
-
介绍
DTD是一个XML的约束,可以规定XML可用的标签,规定标签出现的次序,规定标签的嵌套方式。
-
DTD约束文档
bookdtd.dtd
<!--
复制内容如下到XML文件中:
<!DOCTYPE 书架 SYSTEM "bookdtd.dtd">
-->
<!--ELEMENT表示元素 书架是根标签 (书+)书架里面子元素是书 书可以有一本或多本-->
<!ELEMENT 书架 (书+)>
<!--书也是一个元素 书里面的子元素是 书名 作者 售价-->
<!ELEMENT 书 (书名,作者,售价)>
<!--书名也是一个元素 书名是一个文本-->
<!ELEMENT 书名 (#PCDATA)>
<!--作者也是一个元素 书名是一个文本-->
<!ELEMENT 作者 (#PCDATA)>
<!--售价也是一个元素 书名是一个文本-->
<!ELEMENT 售价 (#PCDATA)> -
DTD引入方式
1.内部DTD,在XML文档内部嵌入DTD,只对当前XML有效
<!DOCTYPE 根元素 [...//具体语法]>
2.外部DTD—本地DTD
<!DOCTYPE 根元素 SYSTEM "bookshelf.dtd"> "bookshelf.dtd"表示dtd名称
3.外部DTD—公共DTD
<!DOCTYPE 根标签 PUBLIC "dtd的名字" "网络上的位置">引入一定不会让你写,现成的语句你复制就可以了。
-
按照上面的dtd约束编写XML
-
DTD约束的符号介绍
* 表示可以出现任意次
+ 表示可以出现一次或多次
? 表示可以出现0次或1次
, 表示需要顺序出现
| 表示或
3.Schema约束
-
介绍
-
Schema约束是约束界的龙头老大,可以对数据类型做更加精准的限制。在后期xml中更多的使用Schema约束。
-
Schema约束的文件名以.xsd结尾。
-
-
Schema约束文档
-
bookschema.xsd
<?xml version="1.0" encoding="UTF-8" ?>
<!-- 传智播客教学实例文档.将注释中的以下内容复制到要编写的xml的声明下面
复制内容如下到XML文件中:
<书架 xmlns="http://www.itcast.cn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.itcast.cn bookSchema.xsd" >
-->
<!--头信息-->
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.itheima.cn"
elementFormDefault="qualified">
<!--这是一个元素 名字叫书架-->
<xs:element name='书架'>
<!--这是一个嵌套元素-->
<xs:complexType>
<!--sequence表示顺序 子元素最多出现2次-->
<xs:sequence maxOccurs='2'>
<!--子元素的名字叫 书-->
<xs:element name='书'>
<!--书 也是一个嵌套元素-->
<xs:complexType>
<!--子元素也是顺序出现 可以出现最少1次 最多无限-->
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<!--书的子元素 叫 书名 是字符串类型-->
<xs:element name='书名' type='xs:string'/>
<!--书的子元素 叫 作者 是字符串类型-->
<xs:element name='作者' type='xs:string'/>
<!--书的子元素 叫 售价 是小数类型-->
<xs:element name='售价' type='xs:double'/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema> -
-
根据上面的Schema约束编写XML
<书架 xmlns="http://www.itheima.cn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.itheima.cn yueshu/bookSchema.xsd">
<书>
<书名>java从入门到放弃</书名>
<作者>吴彦祖</作者>
<售价>99.8</售价>
</书>
<书>
<书名>数据库从入门到跑路</书名>
<作者>曹琪</作者>
<售价>999.8</售价>
</书>
</书架> -
结论
-
我们是根据约束去写XML, 我们不会写约束,约束是框架提供的或者是公司提供的
-
3.DOM4J
1.解析方式
DOM: 把整个XML文件作为树的方式直接加载到内存中。
优点:整个文件在内存中,可以对文件的内容进行增删改查
缺点:对内存的要求太大,可能导致内存溢出
SAX: 边读取边操作,把整个树分开,读到哪里就操作到哪里,操作完就释放内存,再去读下一段内容
优点:不占用太大的内存,不会出现内存问题
缺点:只能查询对应的内容,不能对元素做增删改操作。
2.解析开发包
JAXP:是java自带的解析开发包。使用的时候不需要导入jar包
DOM4J: 4-->for J-->java。是非常优秀的第三方开发包。在使用之前需要导入jar包。
JSOUP: 是专门用于解析HTML的技术。
3.DOM4J解析
-
方法介绍
创建解析器对象:
SAXReader sr = new SAXReader();
解析器读取文件方法:
Document doc = sr.read(String fileName);
Document的方法:
getRootElement() : 获取根元素
节点中的方法:
elements() : 获取当前元素的子元素
element(String name) : 根据元素名获取指定子元素(如果有多个就获取到第一个)
getName() : 获取元素的元素名
attributeValue(String name) : 获取当前元素下某个属性的值
elementText(String name) : 获取指定子元素的文本值,参数是子元素名称
getText() : 获取当前元素的文本值
-
代码演示
-
public class Demo01DOM4J { public static void main(String[] args) throws DocumentException { //获取解析器对象 SAXReader reader = new SAXReader(); //读取文件 Document document = reader.read("day22_2\tianqi.xml"); //获取根元素 Element root = document.getRootElement(); //elements() : 获取当前元素的子元素 List<Element> elements = root.elements(); //遍历集合 for (Element e : elements) { System.out.println(e); } System.out.println("---------------------------"); //element(String name) : 根据元素名获取指定子元素(如果有多个重名就获取到第一个) Element e = root.element("上海"); System.out.println(e); System.out.println("---------------------------"); //getName() : 获取元素的元素名 System.out.println(root); System.out.println(root.getName()); //-------------------------- //获取北京里面的最高温度这个元素 Element maxwd = root.element("北京").element("温度").element("最高温度"); System.out.println(maxwd.getName()); //最高温度 //-------------------------- System.out.println("---------------------------"); //attributeValue(String name) : 获取当前元素下某个属性的值 String s = root.element("北京").attributeValue("province"); System.out.println(s); System.out.println("---------------------------"); //elementText(String name) : 获取指定子元素的文本值,参数是子元素名称 //获取北京的最高温度 Element wd = root.element("北京").element("温度"); //获取温度里面子元素最高温度的值 String s1 = wd.elementText("最高温度"); System.out.println(s1); //getText() : 获取当前元素的文本值 System.out.println("-----------------------------"); //获取北京的最高温度 Element mwd = root.element("北京").element("温度").element("最高温度"); //获取当前元素的值 String s2 = mwd.getText(); System.out.println(s2); } }
4.XPath演示
-
-
刚才我们发现,DOM4J原始写法太过于复杂,复杂在需要一层一层的获取子元素。
-
XPath的作用是快速的直接定位到目标元素。
-
XPath是一种路径的写法,下面的两个方法中支持XPath的写法。
-
Node叫做是节点,DOM里面所有的类型都是Node的子类
-
比如Document Element Attribute 都是 Node的子类
-
-
-
Node中的两个方法可以使用XPath:
List selectNodes("表达式") :使用Xpath作为参数查找多个节点
Node selectSingleNode("表达式") :使用Xpath作为参数查找某个节点(默认获取第一个)-
Xpath表达式写法
-
绝对路径表达式方式
-
以/开头的路径就是绝对路径
// 以单/开头叫绝对路径,绝对路径必须从根元素开始写
//获取天气预报中上海子元素
List<Element> list = document.selectNodes("/天气预报/上海");
//遍历集合
for (Element element : list) {
System.out.println(element);
}
System.out.println("---------------------");
//Node selectSingleNode("表达式") :使用Xpath作为参数查找某个节点(默认获取第一个)
//获取天气预报中第一个上海子元素
Node node = document.selectSingleNode("/天气预报/上海");
System.out.println(node); -
-
相对路径表达式方式
-
不以单/开头的路径叫相对路径,相对路径相对的是当前元素
//不以单/开头的路径叫相对路径,相对于当前元素
Node node1 = document.selectSingleNode("/天气预报/北京/温度");
System.out.println(node1);
//用相对路径的写法获取湿度
Node node2 = node1.selectSingleNode("../湿度");
System.out.println(node2);
System.out.println("------------------------------------------");
Node node3 = document.selectSingleNode("/天气预报/上海/温度/最高温度");
Node node4 = node3.selectSingleNode("../../湿度");
System.out.println(node4.getText()); // 50% -
-
全文搜索路径表达式方式
-
//代表忽略中间的路径,不管中间有多少级
//全文搜索
//获取文本中的所有最高温度
List<Element> list1 = document.selectNodes("//最高温度");
//遍历集合
for (Element e : list1) {
System.out.println(e.getText());
}
System.out.println("--------------------------------");
//获取广州里面的所有最高温度
List<Element> list2 = document.selectNodes("//广州//最高温度");
//遍历集合
for (Element e : list2) {
System.out.println(e);
}
System.out.println("-----------------");
//获取广州里面的直接的最高温度
List<Element> list3 = document.selectNodes("//广州/温度/最高温度");
for (Element e : list3) {
System.out.println(e);
} -
-
谓语条件查询 (了解)
可以对属性进行更精细的判断
//谓语查询
List<Element> list4 = document.selectNodes("//最高温度[@level='CC']");
//遍历集合
for (Element e : list4) {
System.out.println(e.getText());
}
总结
-
-