java回顾之XML和dom4j
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());
 }
 总结
- 
 
- 
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号