随着 JSON 等一些技术的普及,似乎 XML 的路子越来越窄,虽然 XML 的一些功能被其他的一些技术代替,但是学习 XML 还是非常有必要,如果用 XML 存储一些大量数据,还是有一定优势的,就算你不管这些,但是现有的很多框架以及技术的配置文件都存在于 XML 中,最起码你得对它的结构以及一些基本用法有一定了解。

1. 基本概述

1.1 概念

XML:Extensible Markup Language:可扩展标记型语言
标记型:使用标签来操作,html就是一种常见的标记型语言
可扩展:可以自定义标签,甚至可以用中文写标签 Eg:<person></person <张三><张三>

1.2 用途

xml 主要用来存储数据,体现在作配置文件,或者充当小型数据库,在网络中传输数据

1.2.1 配置文件:例如配置mysql数据库

前面我们常常书写 一个 jdbc.properties 文件来做配置文件,好处呢就是如果想修改数据库的信息,不需要修改源代码,只要修改配置文件就可以了,而 xml 也可以作为配置文件来使用

  1. url=jdbc:mysql://localhost:3306/db1
  2. user=root
  3. password=root99
  4. driver=com.mysql.jdbc.Driver

1.2.2 充当小型数据库

我们可以在 XML 中存储一些数据,让它充当一个小型的数据库

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <student>
  3. <stu>
  4. <id>001</id>
  5. <name>zhangsan</name>
  6. <age>20</age>
  7. </stu>
  8. <stu>
  9. <id>002</id>
  10. <name>lisi</name>
  11. <age>30</age>
  12. </stu>
  13. </student>

1.2.3 传输数据

在网络编程中,我们或多或少接触过,例如如何实现一个简单的聊天室,基本原理是这样的,一个服务器端,多个客户端,当客户端1发送数据后,服务器端接收到数据,并且对数据进行一定的审核(是否有非法敏感字)以及格式的处理,再将数据发送到每一个客户端中

刚开始的时候,我们一般选择使用字符串直接传递内容,但是却不是很利于程序的后期维护,而使用xml就能对后期程序的维护更加友好

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <message id="1">
  3. <sender>账号1</sender>
  4. <getter>账号2</getter>
  5. <content>发送的信息</content>
  6. <ip>ip地址</ip>
  7. </message>

2. XML 语法

XML 文档的后缀名为 .xml

2.1 文档声明

创建一个 xml 文件后,第一步就是 必须要有 一个文档声明(写了文档声明之后,表写xml文件的内容)

  1. <?xml version="1.0" encoding="UTF-8"?>
  • version : xml版本,必须写
  • encoding:xml编码 常见编码: GBK、UTF-8、ISO8859-1(不包含中文)
    • 保存时编码和设置打开时候的编码需要一致,否则会出现乱码
  • standalone:是否需要依赖其他文件 yes/no

    2.2 标签的定义

    注意事项
  1. 有始有终:<person></peoson>
  2. 合理嵌套:<aa><bb></bb></aa>
  3. 空格和换行均当做内容来解析,所以可能我们需要注意一些缩进的问题

名称规则

  1. xml 代码区分大小写
  2. 名称不能以数字或者标点符号开始
  3. 不能以 xml、XML、Xml等开头
  4. 不能包含空格和冒号

    2.3 属性的定义

  5. 一个标签上可有多个属性 <person id1="aaa" id2="bbb"></person>

  6. 属性名称和值之间使用 = 连接,属性值用引号包起来(单引号和双引号都可以)

    2.4 注释

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <!-- xml注释 -->
    注释不能嵌套,并且不能放到第一行,第一行必须方式文档声明

    2.5 特殊字符

    如果想在xml中输入特殊字符,需要对字符进行转义,因为 < 等会被当做标签
字符 转义字符 描述
& &
< < 小于号
> > 大于号
双引号
单引号

若多个字符都需要转义,则可以将这些内容存放到CDATA里面

  1. <![CDATA[ 内容 ]]>

2.6 PI指令 (处理指令)

可以在 xml 设置样式

  1. <?xml-stylesheet type="text/css" href="css的路径"?>

3. XML 约束

为什么需要用到约束呢?比如我们现在定义一个 student.xml文件,我们想要在其中保存关于学生的信息,例如id,name,age,但是如果随便写入一个标签 例如 <你好> 从语法的角度上虽然是符合规范的,但是这显然与我们想要存储的东西没有任何关系,所以我们需要通过xml约束技术,约束xml中只能出现的元素

分类

  • DTD:一种相对简单的约束技术
  • Schema:一种相对复杂的约束技术,看懂即可

    3.1 dtd 的引入方式(三种)

    3.1.1 使用内部的dtd文件,即将约束规则定义在xml文档中

    1. <!DOCTYPE 根元素名称 [
    2. <!ELEMENT person (name,age)>
    3. <!ELEMENT name (#PCDATA)>
    4. <!ELEMENT age (#PCDATA)>
    5. ]>

    3.1.2 引入外部的dtd文件

    1. <!DOCTYPE 根元素名称 SYSTEM "dtd路径">

    3.1.3 使用外部的dtd文件(网络上的dtd文件)

    ```xml <!DOCTYPE 根元素 PUBLIC “DTD名称” “DTD文档的URL”>

例如使用 struts2框架 使用配置文件 所使用 外部的dtd文件

<!DOCTYPE struts PUBLIC “-//Apache Software Foundation//DTD Struts Configuration 2.0//EN”
http://struts.apache.org/dtds/struts-2.0.dtd">

  1. <a name="FPFpq"></a>
  2. ## 3.2 使用dtd定义元素
  3. ```xml
  4. <!ELEMENT 元素名 约束>

3.2.1 简单元素(没有子元素)

  1. ELEMENT name (#PCDATA)>
  2. (#PCDATA): 约束name是字符串类型
  3. EMPTY : 元素为空(没有内容)
  4. - <sex></sex>
  5. ANY:任意

3.2.2 复杂元素

  1. <!-- 语法 -->
  2. <!ELEMENT person (id,name,age,)>
  3. 子元素只能出现一次
  4. <!ELEMENT 元素名称 (子元素)>
  5. <!-- 子元素出现次数 -->
  6. * :一次多或多次
  7. ?:零次或一次
  8. * :零次或多次
  9. <!-- 子元素直接使用逗号隔开 -->
  10. 表示元素出现的顺序
  11. <!-- 子元素直接使用 | -->
  12. 表示元素只能出现其中的任意一个

3.3 使用dtd定义属性

  1. <!-- 语法 -->
  2. <!ATTLIST 元素名称
  3. 属性名称 属性类型 属性的约束
  4. >
  5. <!-- 属性类型 --> CDATA: 字符串
  6. <!ATTLIST birthday
  7. ID1 CDATA #REQUIRED
  8. >
  9. <!-- 枚举 -->
  10. 表示只能在一定的范围内出现值,但是只能每次出现其中的一个,红绿灯效果
  11. <!ATTLIST age
  12. ID2 (AA|BB|CC) #REQUIRED
  13. >
  14. <!-- ID: 值只能是字母或者下划线开头 -->
  15. <!ATTLIST name
  16. ID3 ID #REQUIRED
  17. >
  18. <!-- 属性的约束 -->
  19. #REQUIRED:属性必须存在
  20. #IMPLIED:属性可有可无
  21. #FIXED: 表示一个固定值 #FIXED "AAA"
  22. 属性的值必须是设置的这个固定值
  23. <!ATTLIST sex
  24. ID4 CDATA #FIXED "ABC"
  25. >
  26. 直接值
  27. 不写属性,使用直接值
  28. 写了属性,使用设置那个值
  29. <!ATTLIST school
  30. ID5 CDATA "WWW"
  31. >

3.4 Schema约束

schema 符合 xml 的语法,一个 xml 中可以有多个 schema ,多个 schema 使用名称空间区分(类似于java包名)dtd 里面有PCDATA类型,但是在 schema 里面可以支持更多的数据类型
后缀名:xsd

  1. 引入:
  2. 填写xml文档的根元素
  3. 引入xsi前缀. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. 表示xml文件是一个约束文件
  5. 引入xsd文件命名空间. xsi:schemaLocation="http://www.bwh.cn/xml student.xsd"
  6. 使用一个使用schema约束文件,直接通过这个地址引入约束文件
  7. 通常使用一个url地址防止重名
  8. 为每一个xsd约束声明一个前缀,作为标识 xmlns="http://www.bwh.cn/xml"

3.4.1 看xml中有多少个元素

  1. <element>

3.4.2 看简单元素和复杂元素

  1. <element name="person">
  2. <complexType>
  3. <sequence>
  4. <element name="name" type="string"></element>
  5. <element name="age" type="int"></element>
  6. </sequence>
  7. </complexType>
  8. </element>

3.4.3 被约束文件里面引入约束文件

  1. <person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xmlns="http://www.bwh.cn/20151111"
  3. xsi:schemaLocation="http://www.bwh.cn/20151111 1.xsd">
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. -- 表示xml是一个被约束文件
  6. xmlns="http://www.bwh.cn/20151111"
  7. -- 是约束文档里面 targetNamespace
  8. xsi:schemaLocation="http://www.bwh.cn/20151111 1.xsd">
  9. -- targetNamespace 空格 约束文档的地址路径

可以约束属性

  1. A: <sequence>:表示元素的出现的顺序
  2. B: <all>: 元素只能出现一次
  3. C: <choice>:元素只能出现其中的一个
  4. D: maxOccurs="unbounded": 表示元素的出现的次数
  5. E: <any></any>:表示任意元素
  6. 写在复杂元素里面
  7. 写在 </complexType>之前
  8. --
  9. <attribute name="id1" type="int" use="required"></attribute>
  10. - name: 属性名称
  11. - type:属性类型 int stirng
  12. - use:属性是否必须出现 required

4. XML 的解析

很简单的理解解析:有一个xml,在其中读取出需要的数据

4.1 解析方式 dom和sax

DOM:根据xml的层级结构在内存中分配一个树形结构,把xml的标签,属性和文本都封装成对象,一次性加载进内存

  • 优点:操作方便,很容易实现增删改操作
  • 缺点:占内存,有造成内存溢出风险

SAX:采用事件驱动,边读边解析,解析到某一个对象,返回对象名称

  • 优点:不占内存
  • 缺点:只能读取,不能实现增删改操作

    4.1 解析器

    想要解析xml,我们必须了解解析器,不同的公司和组织,提供了针对dom和sax方式的解析器,通过api方式提供 (今天着重讲解两种比较常用的)
  1. jaxp:sun公司所提供针对dom和sax的解析器,效率略低
  2. dim4j:非常优秀的解析器,在实际开发中比较常用
  3. jdom:jdom组织所提供的针对dom和sax解析器
  4. jsoup:jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。
  5. Pull:Android操作系统内置的解析器,sax方式的

    4.3 使用 dom4 操作 XML

    注意:下面的所有java代码中,由于我的代码写在Module中,所以路径加了名字,若直接创建的是项目,只写src/s1.xml即可

    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <student>
    3. <stu id1="love">
    4. <name>zhangsan</name>
    5. <age>20</age>
    6. </stu>
    7. <stu>
    8. <name>lisi</name>
    9. <age>30</age>
    10. </stu>
    11. </student>

    4.3.1 使用dom4j实现查询xml操作

  6. 查询所有name元素里面的值 ```java package cn.ideal.xml.dom4j;

/* 1、创建解析器 2、得到document 3、得到根节点 getRootElement() 返回Element 4、得到所有的p1标签

  1. * elements("p1") 返回list集合
  2. * 遍历list得到每一个p1

5、得到name

  1. * p1下面执行 element("name")方法 返回Element

6、得到name里面的值

  1. * getText方法得到值

*/

import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader;

import java.util.List;

public class TestDom4j1 { //查询xml中所有name元素的值 public static void main(String[] args) throws DocumentException { // 创建解析器 SAXReader saxReader = new SAXReader(); // 得到document Document document = saxReader.read(“code-04_xml/src/s1.xml”); // 得到根节点 Element rootElement = document.getRootElement(); // 得到stu List list = rootElement.elements(“stu”);

  1. // 遍历list
  2. for (Element element : list) {
  3. //element是每一个元素
  4. // 得到name里面的值
  5. Element name1 = element.element("name");
  6. // 得到name里面的值
  7. String s = name1.getText();
  8. System.out.println(s);
  9. }
  10. }

} // 运行结果 zhangsan lisi

  1. 2. **查询第一个name元素的值**
  2. ```java
  3. package cn.ideal.xml.dom4j;
  4. /*
  5. 1、创建解析器
  6. 2、得到document
  7. 3、得到根节点
  8. 4、得到第一个stu元素
  9. element("stu")方法 返回Element
  10. 5、得到p1下面的name元素
  11. element("name")方法 返回Element
  12. 6、得到name元素里面的值
  13. getText方法
  14. */
  15. import org.dom4j.Document;
  16. import org.dom4j.DocumentException;
  17. import org.dom4j.Element;
  18. import org.dom4j.io.SAXReader;
  19. public class TestDom4j2 {
  20. public static void main(String[] args) throws DocumentException {
  21. // 创建解析器
  22. SAXReader saxReader = new SAXReader();
  23. // 得到document对象
  24. Document document = saxReader.read("code-04_xml/src/s1.xml");
  25. // 得到根节点
  26. Element rootElement = document.getRootElement();
  27. // 得到第一个stu元素
  28. Element stu = rootElement.element("stu");
  29. // 得到stu下面的name元素
  30. Element name1 = stu.element("name");
  31. // 得到name的值
  32. String s1 = name1.getText();
  33. System.out.println(s1);
  34. }
  35. }
  36. //运行结果
  37. zhangsan
  1. 获取第二个name元素的值 ```java package cn.ideal.xml.dom4j;

import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader;

import java.util.List;

/ 1、创建解析器 2、得到document 3、得到根节点 4、得到所有的stu 返回 list集合 5、遍历得到第二个stu 使用list下标得到 get方法,集合的下标从 0 开始,想要得到第二个值,下标写 1 6、得到第二个p1下面的name element(“name”)方法 返回Element 7、得到name的值 getText方法 / public class TestDom4j3 { public static void main(String[] args) throws DocumentException { // 创建解析器 SAXReader saxReader = new SAXReader(); // 得到document Document document = saxReader.read(“code-04_xml/src/s1.xml”); // 得到根节点 Element rootElement = document.getRootElement(); // 得到所有stu List list = rootElement.elements(“stu”); // 得到第二个stu Element stu2 = list.get(1); // 得到stu下的name Element name2 = stu2.element(“name”); // 得到name里面的值 String s2 = name2.getText(); System.out.println(s2); } }

  1. <a name="RIyFP"></a>
  2. ### 4.3.2 使用dom4j实现添加操作
  3. 1. **在第一个p1标签末尾添加一个元素 **`<sex>male</sex>`
  4. ```java
  5. package cn.ideal.xml.dom4j;
  6. import org.dom4j.Document;
  7. import org.dom4j.Element;
  8. import org.dom4j.io.OutputFormat;
  9. import org.dom4j.io.SAXReader;
  10. import org.dom4j.io.XMLWriter;
  11. import java.io.FileOutputStream;
  12. /*
  13. 1、创建解析器
  14. 2、得到document
  15. 3、得到根节点
  16. 4、获取到第一个p1
  17. 使用element方法
  18. 5、在p1下面添加元素
  19. 在p1上面直接使用 addElement("标签名称")方法 返回一个Element
  20. 6、在添加完成之后的元素下面添加文本
  21. 在sex上直接使用 setText("文本内容")方法
  22. 7、回写xml
  23. 格式化 OutputFormat,使用 createPrettyPrint方法,表示一个漂亮的格式
  24. 使用类XMLWriter 直接new 这个类 ,传递两个参数
  25. 第一个参数是xml文件路径 new FileOutputStream("路径")
  26. 第二个参数是格式化类的值
  27. */
  28. public class TestDom4j4 {
  29. public static void main(String[] args) throws Exception {
  30. // 创建解析器
  31. SAXReader saxReader = new SAXReader();
  32. // 得到document
  33. Document document = saxReader.read("code-04_xml/src/s1.xml");
  34. // 得到根节点
  35. Element rootElement = document.getRootElement();
  36. // 得到第一个stu元素
  37. Element stu = rootElement.element("stu");
  38. // 在stu下面直接添加元素
  39. Element sex1 = stu.addElement("sex");
  40. // 在sex下面添加文本
  41. sex1.setText("male");
  42. // 回写xml
  43. OutputFormat prettyPrint = OutputFormat.createPrettyPrint();//有缩进效果
  44. XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("code-04_xml/src/s1.xml"), prettyPrint);
  45. xmlWriter.write(document);
  46. }
  47. }

写一个工具类,简化操作
封装方法的操作,可以省略创建解析器 得到document 以及回写xml的方法,把传递的文件路径,封装成一个常量
好处:可以提高开发速度,可以提交代码可维护性
比如想要修改文件路径(名称),这个时候只需要修改常量的值就可以了,其他代码不需要做任何改变

  1. package cn.ideal.xml.utils;
  2. import org.dom4j.Document;
  3. import org.dom4j.DocumentException;
  4. import org.dom4j.io.OutputFormat;
  5. import org.dom4j.io.SAXReader;
  6. import org.dom4j.io.XMLWriter;
  7. import java.io.FileOutputStream;
  8. import java.io.IOException;
  9. public class Dom4jUtils {
  10. public static final String PATH = "code-04_xml/src/s1.xml";
  11. // 返回document
  12. public static Document getDocument(String path) {
  13. // 创建解析器
  14. SAXReader saxReader = new SAXReader();
  15. // 得到document
  16. try {
  17. Document document = saxReader.read(path);
  18. return document;
  19. } catch (DocumentException e) {
  20. e.printStackTrace();
  21. }
  22. return null;
  23. }
  24. // 回写xml的方法
  25. public static void xmlWriters(String path, Document document) {
  26. try {
  27. OutputFormat prettyPrint = OutputFormat.createPrettyPrint();//有缩进效果
  28. XMLWriter xmlWriter = new XMLWriter(new FileOutputStream(path), prettyPrint);
  29. xmlWriter.write(document);
  30. } catch (IOException e) {
  31. e.printStackTrace();
  32. }
  33. }
  34. }

我们上面执行添加操作的代码就可以简化为

  1. package cn.ideal.xml.dom4j;
  2. import cn.ideal.xml.utils.Dom4jUtils;
  3. import org.dom4j.Document;
  4. import org.dom4j.Element;
  5. public class TestDom4j5 {
  6. public static void main(String[] args) throws Exception {
  7. Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
  8. // 得到根节点
  9. Element rootElement = document.getRootElement();
  10. // 得到第一个stu元素
  11. Element stu = rootElement.element("stu");
  12. // 在stu下面直接添加元素
  13. Element sex1 = stu.addElement("sex");
  14. // 在sex下面添加文本
  15. sex1.setText("male");
  16. // 回写xml
  17. Dom4jUtils.xmlWriters(Dom4jUtils.PATH, document);
  18. }
  19. }
  1. 使用dom4j实现在特定位置添加元素

在第一个stu下面的name标签前添加 <id>001</id>

  1. package cn.ideal.xml.dom4j;
  2. import cn.ideal.xml.utils.Dom4jUtils;
  3. import org.dom4j.Document;
  4. import org.dom4j.DocumentHelper;
  5. import org.dom4j.Element;
  6. import java.util.List;
  7. /*
  8. 1、创建解析器
  9. 2、得到document
  10. 3、得到根节点
  11. 4、获取到第一个p1
  12. 5、获取p1下面的所有的元素
  13. ** elements()方法 返回 list集合
  14. ** 使用list里面的方法,在特定位置添加元素
  15. ** 首先创建元素 在元素下面创建文本
  16. - 使用DocumentHelper类方法createElement创建标签
  17. - 把文本添加到标签下面 使用 setText("文本内容")方法
  18. ** list集合里面的 add(int index, E element)
  19. - 第一个参数是 位置 下标,从0开始
  20. - 第二个参数是 要添加的元素
  21. 6、回写xml
  22. */
  23. public class TestDom4j6 {
  24. // 在第一个stu下面的name标签前添加<id>001</id>
  25. public static void main(String[] args) {
  26. Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
  27. // 得到根节点
  28. Element rootElement = document.getRootElement();
  29. // 得到第一个stu元素
  30. Element stu = rootElement.element("stu");
  31. // 获取stu下全部元素
  32. List<Element> list = stu.elements();
  33. // 创建元素
  34. Element id = DocumentHelper.createElement("id");
  35. // 在id下面创建文本
  36. id.setText("001");
  37. // 在特定位置添加
  38. list.add(0, id);
  39. Dom4jUtils.xmlWriters(Dom4jUtils.PATH, document);
  40. }
  41. }

4.3.3 使用dom4j实现修改节点的操作

修改第一个p1下面的age元素的值为18

  1. package cn.ideal.xml.dom4j;
  2. /*
  3. 1、得到document
  4. 2、得到根节点,然后再得到第一个p1元素
  5. 3、得到第一个p1下面的age
  6. element("")方法
  7. 4、修改值是 30
  8. 使用setText("文本内容")方法
  9. 5、回写xml
  10. */
  11. import cn.ideal.xml.utils.Dom4jUtils;
  12. import org.dom4j.Document;
  13. import org.dom4j.Element;
  14. public class TestDom4j7 {
  15. public static void main(String[] args) {
  16. //得到document
  17. Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
  18. //得到根节点
  19. Element rootElement = document.getRootElement();
  20. //得到第一个stu元素
  21. Element stu = rootElement.element("stu");
  22. //得到第一个stu下面的age
  23. Element age = stu.element("age");
  24. age.setText("18");
  25. //回写xml
  26. Dom4jUtils.xmlWriters(Dom4jUtils.PATH, document);
  27. }
  28. }

4.3.4 使用dom4j实现删除节点的操作

  1. package cn.ideal.xml.dom4j;
  2. import cn.ideal.xml.utils.Dom4jUtils;
  3. import org.dom4j.Document;
  4. import org.dom4j.Element;
  5. public class TestDom4j8 {
  6. public static void main(String[] args) {
  7. //得到document
  8. Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
  9. //得到根节点
  10. Element rootElement = document.getRootElement();
  11. //得到第一个stu元素
  12. Element stu = rootElement.element("stu");
  13. //得到第一个stu下面的age
  14. Element id = stu.element("id");
  15. stu.remove(id);
  16. //回写xml
  17. Dom4jUtils.xmlWriters(Dom4jUtils.PATH, document);
  18. }
  19. }

4.3.5 使用dom4j获取属性的操作

  1. package cn.ideal.xml.dom4j;
  2. import cn.ideal.xml.utils.Dom4jUtils;
  3. import org.dom4j.Document;
  4. import org.dom4j.Element;
  5. public class TestDom4j9 {
  6. public static void main(String[] args) {
  7. //得到document
  8. Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
  9. //得到根节点
  10. Element rootElement = document.getRootElement();
  11. //得到第一个stu元素
  12. Element stu = rootElement.element("stu");
  13. //得到stu里面的属性值
  14. String value = stu.attributeValue("id1");
  15. System.out.println(value);
  16. }
  17. }

4.3.6 使用dom4j支持xpath具体操作

XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言

默认的情况下,dom4j不支持xpath
如果想用,需要引入支持xpath的jar包,使用 jaxen-1.1-beta-6.jar

  1. 第一种形式
  2. /AAA/CCC/BBB 表示一层一层的,AAA下面CCC下面的BBB
  3. 第二种形式
  4. //BBB: 表示和这个名称相同,表示只要名称是BBB,都得到
  5. 第三种形式
  6. /*: 所有元素
  7. 第四种形式
  8. BBB[1]: 表示第一个BBB元素
  9. BBB[last()]:表示最后一个BBB元素
  10. 第五种形式
  11. //BBB[@id]: 表示只要BBB元素上面有id属性,都得到
  12. 第六种形式
  13. //BBB[@id='b1'] 表示元素名称是BBB,在BBB上面有id属性,并且id的属性值是b1

dom4j里面提供了两个方法,用来支持xpath

  1. // 获取多个节点
  2. selectNodes("xpath表达式")
  3. // 获取一个节点
  4. selectSingleNode("xpath表达式")

使用xpath实现:查询xml中所有name元素的值

  1. package cn.ideal.xml.dom4j.xpath;
  2. import cn.ideal.xml.utils.Dom4jUtils;
  3. import org.dom4j.Document;
  4. import org.dom4j.Node;
  5. import java.util.List;
  6. public class TestDom4jXpath1 {
  7. // 查询xml中所有name元素的值
  8. public static void main(String[] args) {
  9. // 得到document
  10. Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
  11. // 获取所有name元素
  12. List<Node> list = document.selectNodes("//name");
  13. // 遍历list集合
  14. for (Node node : list) {
  15. // node是每一个name元素
  16. // 得到name元素里面的值
  17. String s = node.getText();
  18. System.out.println(s);
  19. }
  20. }
  21. }

4.3.7 使用xpath实现:获取第一个stu下面的name的

  1. package cn.ideal.xml.dom4j.xpath;
  2. import cn.ideal.xml.utils.Dom4jUtils;
  3. import org.dom4j.Document;
  4. import org.dom4j.Node;
  5. public class TestDom4jXpath2 {
  6. public static void main(String[] args) {
  7. // 得到document
  8. Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
  9. Node name1 = document.selectSingleNode("//stu[@id1='love']/name");
  10. // 得到name里面的值
  11. String s1 = name1.getText();
  12. System.out.println(s1);
  13. }
  14. }

4.4 使用 Jsoup 操作 xml

  1. package cn.ideal.xml.jsoup;
  2. import org.jsoup.Jsoup;
  3. import org.jsoup.nodes.Document;
  4. import org.jsoup.nodes.Element;
  5. import org.jsoup.select.Elements;
  6. import java.io.File;
  7. import java.io.IOException;
  8. public class JsoupDemo1 {
  9. public static void main(String[] args) throws IOException {
  10. //获取Documnet对象
  11. //通过类加载器,获取student.xml的path
  12. String path = JsoupDemo1.class.getClassLoader().getResource("student.xml").getPath();
  13. //解析xml文档,加载文档进内存,获取dom树 --> Document
  14. Document document = Jsoup.parse(new File(path), "utf-8");
  15. //获取元素对象 Element
  16. Elements elements = document.getElementsByTag("name");
  17. //获取第一个name
  18. Element element = elements.get(0);
  19. //获取数据
  20. String name = element.text();
  21. System.out.println(name);
  22. }
  23. }

对上述常用对象的解释
1. Jsoup:工具类:可以解析html或xml文档,返回Document
parse:

  1. // 解析xml或html文件
  2. parse (File in, String charsetName)
  3. // 解析xml或html字符串
  4. parse (String html)
  5. // 通过网络路径获取指定的html或xml
  6. parse (URL url, int timeoutMillis)

2. Document:文档对象:代表内存中的dom树
A:获取Element对象

  1. // 根据id属性值获取唯一的element对象
  2. getElementById (String id)
  3. // 根据标签名称获取元素对象集合
  4. getElementsByTag (String tagName)
  5. // 根据属性名称获取元素对象集合
  6. getElementsByAttribute (String key)
  7. // 根据对应的属性名和属性值获取元素对象集合
  8. getElementsByAttributeValue (String key, String value)

3. Elements:元素Element对象的集合。可以近似的认为 **ArrayList<Element>**
A:获取Element对象,同2中
B:获取属性值

  1. String attr(String key):根据属性名称获取属性值

C:获取文本内容

  1. // 获取文本内容
  2. String text()
  3. // 获取标签体的所有内容
  4. String html()

两种更加快捷的查询方式
selector:选择器

  1. Elements select(String cssQuery)
  2. // 具体语法,看文档格式
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <student>
  3. <stu number="stu_001">
  4. <name id="ideal">zhangsan</name>
  5. <age>18</age>
  6. </stu>
  7. <stu number="stu_002">
  8. <name>lisi</name>
  9. <age>30</age>
  10. </stu>
  11. </student>
  1. package cn.ideal.xml.jsoup;
  2. import org.jsoup.Jsoup;
  3. import org.jsoup.nodes.Document;
  4. import org.jsoup.select.Elements;
  5. import java.io.File;
  6. import java.io.IOException;
  7. public class SelectorDemo {
  8. public static void main(String[] args) throws IOException {
  9. //获取Documnet对象
  10. //通过类加载器,获取student.xml的path
  11. String path = JsoupDemo1.class.getClassLoader().getResource("student.xml").getPath();
  12. //解析xml文档,加载文档进内存,获取dom树 --> Document
  13. Document document = Jsoup.parse(new File(path), "utf-8");
  14. //查询name标签
  15. Elements elements1 = document.select("name");
  16. System.out.println(elements1);
  17. System.out.println("--------------");
  18. //查询id值为 stu_001
  19. Elements elements2 = document.select("#ideal");
  20. System.out.println(elements2);
  21. System.out.println("--------------");
  22. Elements elements3 = document.select("stu[number='stu_001']");
  23. System.out.println(elements3);
  24. }
  25. }
  26. // 运行结果
  27. <name id="ideal">
  28. zhangsan
  29. </name>
  30. <name>
  31. lisi
  32. </name>
  33. --------------
  34. <name id="ideal">
  35. zhangsan
  36. </name>
  37. --------------
  38. <stu number="stu_001">
  39. <name id="ideal">
  40. zhangsan
  41. </name>
  42. <age>
  43. 18
  44. </age>
  45. </stu>

XPath

  1. package cn.ideal.xml.jsoup;
  2. import cn.wanghaomiao.xpath.model.JXDocument;
  3. import cn.wanghaomiao.xpath.model.JXNode;
  4. import org.jsoup.Jsoup;
  5. import org.jsoup.nodes.Document;
  6. import java.io.File;
  7. import java.util.List;
  8. public class XpathDemo {
  9. public static void main(String[] args) throws Exception {
  10. // 获取Documnet对象
  11. //通过类加载器,获取student.xml的path
  12. String path = JsoupDemo1.class.getClassLoader().getResource("student.xml").getPath();
  13. //解析xml文档,加载文档进内存,获取dom树 --> Document
  14. Document document = Jsoup.parse(new File(path), "utf-8");
  15. //创建JXDocument对象
  16. JXDocument jxDocument = new JXDocument(document);
  17. //结合xpath语法查询
  18. List<JXNode> jxNodes = jxDocument.selN("//stu");
  19. for (JXNode jxNode : jxNodes) {
  20. System.out.println(jxNode);
  21. }
  22. }
  23. }
  24. //运行结果
  25. <stu number="stu_001">
  26. <name id="ideal">
  27. zhangsan
  28. </name>
  29. <age>
  30. 18
  31. </age>
  32. </stu>
  33. <stu number="stu_002">
  34. <name>
  35. lisi
  36. </name>
  37. <age>
  38. 30
  39. </age>
  40. </stu>
  1. //查询stu标签下的name标签
  2. List<JXNode> jxNodes = jxDocument.selN("//student/name");
  3. //查询stu标签下带有id属性且属性值ideal的name标签
  4. List<JXNode> jxNodes = jxDocument.selN("//stu/name[@id='ideal']");