Java=XML解析,Dom4j,XPath

1.xml解析:Dom解析,SAX解析

2.Dom4j

3.XPath解析

一。XML

eXtendside markup language 可扩展的标记语言

XML 指可扩展标记语言( EXtensible Markup Language
XML 是一种 标记语言 ,很类似 HTML HTML 文件也是 XML 文档
XML 的设计宗旨是 传输数据 ,而非显示数据
XML 标签没有被预定义。您需要 自行定义标签
XML 被设计为具有 自我描述性 ( 就是易于阅读 )
XML W3C 的推荐标准
W3C 1988 2 月发布 1.0 版本, 2004 2 月又发布 1.1 版本,但因为 1.1 版本不能向下兼容 1.0 版本,所以 1.1
有人用。同时,在 2004 2 W3C 又发布了 1.0 版本的第三版。我们要学习的还是 1.0 版本。

xml与Html的差异“

XML 不是 HTML 的替代。
XML HTML 为不同的目的而设计。
XML 被设计为传输和存储数据,其焦点是数据的内容。
HTML 被设计用来显示数据,其焦点是数据的外观。
HTML 旨在显示信息,而 XML 旨在传输信息。
 
 
xml的格式:
 
<?xml version="1.0" encoding="utf-8" ?>
<person id="abc">
    <name>王三</name>
    <age>12</age>
    <sex>男</sex>
</person>

xml的作用:

可以用来保存数据

可以用来做配置文件

数据传输载体

XML 在企业开发中主要有两种应用场景:
1 XML 可以存储数据 , 作为数据交换的载体 ( 使用 XML 格式进行数据的传输 )
2 XML 也可以作为配置文件,例如后面框架阶段我们学习的 Spring 框架的配置 (applicationContext.xml) 都是通过
XML 进行配置的(企业开发中经常使用的)
 
 

3.xml的组成元素

XML 文件中常见的组成元素有 : 文档声明、元素、属性、注释、转义字符、字符区。

3.1文档声明:

<?xml version="1.0" encoding="utf-8" ?>
 
1. 使用 IDE 创建 xml 文件时就带有文档声明 .
2. 文档声明必须为 <?xml 开头,以? > 结束
3. 文档声明必须从文档的 0 0 列位置开始
4. 文档声明中常见的两个属性:
version :指定 XML 文档版本。必须属性,这里一般选择 1.0
encoding :指定当前文档的编码,可选属性,默认值是 utf-8

3.2 元素element:

格式 1: <person></person>
格式 2: <person/>
 
1. 元素是 XML 文档中最重要的组成部分;
2. 普通元素的结构由开始标签、元素体、结束标签组成。
3. 元素体:元素体可以是元素,也可以是文本,例如: <person><name> 张三 </name></person>
4. 空元素:空元素只有标签,而没有结束标签,但元素必须自己闭合,例如: <sex/>
5. 元素命名
区分大小写
不能使用空格,不能使用冒号
不建议以 XML xml Xml 开头
6. 格式化良好的 XML 文档,有且仅有一个根元素。

3.3 属性

<person id = "110" >
 
1. 属性是元素的一部分,它必须出现在元素的开始标签中
2. 属性的定义格式:属性名 =“ 属性值 ,其中属性值必须使用单引或双引号括起来
3. 一个元素可以有 0~N 个属性,但一个元素中不能出现同名属性
4. 属性名不能使用空格 , 不要使用冒号等特殊字符,且必须以字母开头

3.4 注释

<!-- 注释内容 -->
XML 的注释与 HTML 相同,既以 <! -- 开始, -- > 结束。

3.5 转义字符

XML 中的转义字符与 HTML 一样。因为很多符号已经被文档结构所使用,所以在元素体或属性值中想使用这些符号
就必须使用转义字符(也叫实体字符),例如: ">" "<" "'" """ "&"
 
 
注意:严格地讲,在 XML 中仅有字符 "<" "&" 是非法的。省略号、引号和大于号是合法的,但是把它们替换为实
体引用是个好的习惯。
示例:
 
 
假如您在 XML 文档中放置了一个类似 "<" 字符,那么这个文档会产生一个错误,这是因为解析器会把它解释为新
元素的开始。因此你不能这样写
<message> if salary < 1000 then </message>
 
为了避免此类错误,需要把字符 "<" 替换为实体引用,就像这样:
<message> if salary &lt; 1000 then </message>
 

3.6.字符区

<![CDATA[
文本数据
]]>
1. CDATA 指的是不应由 XML 解析器进行解析的文本数据( Unparsed Character Data
2. CDATA 部分由 "" 结束;
3. 当大量的转义字符出现在 xml 文档中时,会使 XML 文档的可读性大幅度降低。这时如果使用 CDATA 段就会好一
些。
 
<! [ CDATA [
if salary < 1000 then
]]
 
注意:
CDATA 部分不能包含字符串 "]]>" 。也不允许嵌套的 CDATA 部分。
标记 CDATA 部分结尾的 "]]>" 不能包含空格或折行

4.XML的文件的约束

在xml技术里,可以编写一个文档来约束一个xml文档的书写规范,这就是xml规范

常见的xml约束:dtd,Schema

(1)DTD约束

DTD是文档类型定义;Document Type Definition ,DTD 可以定义在xml 文档中出现的元素,这些元素出现的次序,他们如何相互嵌套,以及XML文档结构的其他详细信息、

语法:

文档声明:

1. 内部 DTD ,在 XML 文档内部嵌入 DTD ,只对当前 XML 有效。
 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE 根元素 [...// 具体语法 ]> <!-- 内部 DTD-->
< 根元素 >
</ 根元素 >
2. 外部 DTD— 本地 DTD DTD 文档在本地系统上,企业内部自己项目使用。
 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE 根元素 SYSTEM "bookshelf.dtd"> <!-- 外部本地 DTD-->
< 根元素 >
</ 根元素
3. 外部 DTD— 公共 DTD DTD 文档在网络上,一般都有框架提供 , 也是我们使用最多的 .
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
</web-app>

元素的声明:

约束元素的嵌套层级

语法:

<!ELEMENT 父标签 (子标签 1 ,子标签 2 >
 
代码
 
<!ELEMENT 书架 ( +)> <!-- 约束根元素是 " 书架 " " 书架 " 子元素为 " " “+” 为数量词,请看下面介绍 -
->
<!ELEMENT ( 书名 , 作者 , 售价 )> <!-- 约束 " " 子元素依次为 书名 作者 售价 “+” 书元素至少 1
-->
约束元素体里面的数据
 
<!ELEMENT 标签名字 标签类型
 

标签类型

代码

<!ELEMENT 书名 ( #PCDATA )> <!--" 书名 " 元素体为字符串数据 -->
<!ELEMENT 作者 ( #PCDATA )> <!--" 作者 " 元素体为字符串数据 -->
<!ELEMENT 售价 ( #PCDATA )> <!--" 售价 " 元素体为字符串数据 -->
<!ELEMENT 出版日期 ANY > <!--" 出版日期 " 元素体为任意类型 -->
<!ELEMENT 版本号 EMPTY > <!--" 版本号 " 元素体为空元素 -->

数量词

属性声明:

语法:

<!ATTLIST 标签名称
属性名 1 属性类 1 属性说 1
属性名 2 属性类 2 属性说 2
>

代码“

<!ATTLIST <!-- 设置 " " 元素的的属性列表 -->
id ID #REQUIRED <!--"id" 属性值为必须有 -->
编号 CDATA #IMPLIED <!--" 编号 " 属性可有可无 -->
出版社 ( 清华 | 北大 ) " 清华 " <!--" 出版社 " 属性值是枚举值,默认为 清华 ”-->
type CDATA #FIXED "IT" <!--"type" 属性为文本字符串并且固定值为 "IT"-->
>

5.Schema约束:

概念:

Schema语言也可作为XSD(XML Schema Definition)

Schema比DTD强大,是DTD的替代者

Schema本身也是XML文档,单Schema文档扩展名为xsd,而不是xml

Schema功能更强大,数据类型约束更完善、

约束体验

名称空间

一个 XML 文档最多可以使用一个 DTD 文件 , 但一个 XML 文档中使用多个 Schema 文件,若这些 Schema 文件中定义了
相同名称的元素时 , 使用的时候就会出现名字冲突。这就像一个 Java 文件中使用了 import java.util.*
import java.sql.* 时,在使用 Date 类时,那么就不明确 Date 是哪个包下的 Date 了。同理 , XML 文档中就需
要通过名称空间 (namespace) 来区分元素和属性是来源于哪个约束中的。名称空间就在在根元素后面的内容 , 使用
xmlns 到引入约束 。
当一个 XML 文档中需要使用多个 Schema 文件的时候 , 有且仅有一个使用缺省的 , 其他的名称空间都需要起别名 。
参考资料中的 applicationContext.xml 文件 (spring 框架的配置文件 )
 
xmlns="http://www.abc.cn"
<!-- 缺省的名称空间 . 使用此约束中的元素的时候只需要写元素名即可 例如 :< ></ > -->
xmlns:aa="http://java.sun.com"
<!-- aa 就是此约束的别名 , 使用此约束中的元素的时候就需要加上别名 例如 :<aa: ></aa: > -->
 
总之名称空间就是用来处理元素和属性的名称冲突问题,与 Java 中的包是同一用途。如果每个元素和属性都有自己
的名称空间,那么就不会出现名字冲突问题,就像是每个类都有自己所在的包一样,那么类名就不会出现冲突。
 
 
虽然 schema 功能比 dtd 强大,但是编写要比 DTD 复杂,同样以后我们在企业开发中也很少会自己编写 schema
件。
xml 编写与约束内容已经完成了,根据 xml 的作用我们了解到,无论是 xml 作为配置文件还是数据传输,我们的程序
都要获取 xml 文档中的数据以便我们进行具体的业务操作,

二。Dom4j

1.XML解析

解析描述:

当将数据存储在 XML 后,我们就希望通过程序获取 XML 的内容。如果我们使用 Java 基础所学的 IO 知识是可以完成
的,不过你学要非常繁琐的操作才可以完成,且开发中会遇到不同问题(只读、读写)。人们为不同问题提供不同
的解析方式,使用不同的解析器进行解析,方便开发人员操作 XML
2.解析方式和解析器
 
开发中比较常见的解析方式有三种,如下:
1. DOM:要求解析器把整个XML文档装载到内存,并解析成一个Document对象
a )优点:元素与元素之间保留结构关系,故可以进行增删改查操作。
b )缺点: XML 文档过大,可能出现内存溢出
2. SAX:是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。并以事件驱动的方式进
行具体解析,每执行一行,都触发对应的事件。
a )优点:处理速度快,可以处理大文件
b )缺点:只能读,逐行后将释放资源,解析操作繁琐。
3. PULLAndroid内置的XML解析方式,类似SAX

解析器:

就是根据不同的解析方式提供具体实现。有的解析器操作过于繁琐,为了方便开发人员,有提供易
于操作的解析开发包
 
常见的解析开发包
JAXPsun公司提供支持DOMSAX开发包
Dom4j:比较简单的的解析开发包(常用)
JDom:与Dom4j类似
Jsoup:功能强大DOM方式的XML解析开发包,尤其对HTML解析更加方便

4.Dom4j 的基本使用

(1)DOM 解析原理及结构模型

解析原理

XML DOM HTML DOM 一样, XML DOM 将整个 XML 文档加载到内存,生成一个 DOM 树,并获得一个
Document 对象,通过 Document 对象就可以对 DOM 进行操作。

结构模型

DOM 中的核心概念就是节点,在 XML 文档中的元素、属性、文本,在 DOM 中都是节点!所有的节点都封装到
Document 对象中。
引入 dom4j jar
需要引入 “jar/dom4j-1.6.1.jar” , IDEA 中,选择项目鼠标右键 ---> 弹出菜单 -->open Module settings”--
>Dependencies-->+-->JARs or directories...
 
找到 dom4j-1.6.1.jar, 成功添加之后点击 "OK" 即可
 
dom4j 必须使用核心类 SaxReader 加载 xml 文档获得 Document ,通过 Document 对象获得文档的根元素,然
后就可以操作了。
 
(2)常用方法
 

解析上上述文件:

解析此文件 , 获取每本书的 id , 以及书本名称 , 作者名称和价格 .

5.XPath

介绍:

XPath 使用路径表达式来选取 HTML 文档中的元素节点或属性节点。节点是通过沿着路径 (path) 来选取的。 XPath
在解析 HTML 文档方面提供了一独树一帜的路径思想。

XPath的使用步骤:

步骤 1 :导入 jar (dom4j jaxen-1.1-beta-6.jar)
步骤 2 :通过 dom4j SaxReader 获取 Document 对象
步骤 3 : 利用 Xpath 提供的 api, 结合 xpaht 的语法完成选取 XML 文档元素节点进行解析操作。
 
document常用的api
 
 

XPath语法:

XPath 表达式,就是用于选取 HTML 文档中节点的表达式字符串。
获取 XML 文档节点元素一共有如下 4 XPath 语法方式:
1. 绝对路径表达式方式 例如 : / 元素 / 子元素 / 子子元素 ...
2. 相对路径表达式方式 例如 : 子元素 / 子子元素 .. 或者 ./ 子元素 / 子子元素 ..
3. 全文搜索路径表达式方式 例如 : // 子元素 // 子子元素
4. 谓语(条件筛选)方式 例如 : // 元素 [@attr1=value]
 

1.绝对路径表达式

绝对路径介绍
格式: String xpath="/ 元素 / 子元素 / 子子元素 ...";
绝对路径是以 “/” 开头,一级一级描述标签的层级路径就是绝对路径, 这里注意不可以跨层级
绝对路径是从根元素开始写路径的, 这里开头的 “/” 代表 HTML 文档根元素 ,所以在绝对路径中不可以写根元素
路径
 

2.相对路径表达式

相对路径介绍
格式: String xpath1=" 子元素 / 子子元素 ...";// 获取相对当前路径元素里面的子元素的选取
String xpath2="./ 子元素 / 子子元素 ";//"./" 代表当前元素路径位置
String xpath3="/ 子元素 / 子子元素 ";// 功能与 xpath1 格式功能一样
相对路径就是相对当前节点元素位置继续查找节点,需要使用 JXNode.sel xpath )进行执行相对路径表达

3.全文搜索路径表达式

全文搜索路径介绍
格式: String xpath1="// 子元素 // 子子元素 ";
一个 “/” 符号,代表逐级写路径
2 “//” 符号,不用逐级写路径,可以直接选取到对应的节点,是全文搜索匹配的不需要按照逐层级
 

4.谓语(条件筛选)

介绍
谓语,又称为条件筛选方式,就是根据条件过滤判断进行选取节点
格式:
String xpath1="// 元素 [@attr1=value]";// 获取元素属性 attr1=value 的元素
String xpath2="// 元素 [@attr1>value]/@attr1"// 获取元素属性 attr1>value d 的所有 attr1 的值
String xpath3="// 元素 [@attr1=value]/text()";// 获取符合条件元素体的自有文本数据
String xpath4="// 元素 [@attr1=value]/html()";// 获取符合条件元素体的自有 html 代码数据。
String xpath3="// 元素 [@attr1=value]/allText()";// 获取符合条件元素体的所有文本数据(包含子元素里面的
文本)

演示:

other---

============================================================================

<?xml version="1.0" encoding="UTF-8"?>
<books>
    <book id="01" 出版社="出版社">
        <name>Java编程思想</name>
        <author>James</author>
        <price>98.00</price>
        <body>库存:30</body>
    </book>
    <book id="02" 出版社="出版社">
        <name>JavaEE从入门到精通</name>
        <author>哈哈</author>
        <price>40.00</price>
        <body>库存:20</body>
    </book>
    <book id="03" 出版社="传智出版社">
        <name>Java开发手册</name>
        <author>阿里巴巴</author>
        <price>15.00</price>
        <body>库存:300</body>
    </book>
</books>

解析

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

import java.io.InputStream;
import java.util.List;

/**
 *
 *  请解析出图书信息,并打印。
 *
 */
public class Test01 {

    public static void main(String[] args) throws DocumentException {

        // 获得核心解析器对象
        SAXReader reader = new SAXReader();

        // 加载xml文件到内存生成一个document文档对象
        /*Class clazz = Test01.class;
        InputStream is = clazz.getResourceAsStream("books.xml");
        Document document = reader.read(is);*/

        Document document = reader.read(Test01.class.getResourceAsStream("books.xml"));

        // 获得根元素节点
        Element rootElement = document.getRootElement();
        System.out.println("rootElement:" + rootElement.getName());

        /// 获得所有的子元素节点
        List<Element> elements = rootElement.elements();

        // 遍历
        for (Element element : elements) {
            //System.out.println(element.getName());
            // 获得图书编号
            String id = element.attributeValue("id");
            System.out.println(id);

            // 获得出版社
            String 出版社 = element.attributeValue("出版社");
            System.out.println(出版社);

            // 继续获得book元素节点的子元素节点
            List<Element> eles = element.elements();

            // 继续遍历
            for (Element ele : eles) {
                String name = ele.getName();
                String text = ele.getText();
                System.out.println(name + ": " + text);
            }
        }

    }

}
<?xml version="1.0" encoding="UTF-8"?>
<beans>
    <!--<bean id="Animal" class="com.wsl.demo02.Dog"></bean>-->
    <bean id="Animal" class="com.wsl.demo02.Cat"></bean>
</beans>

解析:

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


public class BeanFactory {

    // 解析beans.xml文件,获得配置的全限定类名,使用反射创建对象
    public static Object getBean(String id){ // id的值为Animal
        
        Object obj = null;
        
        try {
            // 获得核心解析器对象
            SAXReader saxReader = new SAXReader();
            
            // 解析xml文件加载到内存生成一个Document对象
            Document document = saxReader.read(BeanFactory.class.getResourceAsStream("beans.xml"));
            
            // 使用dom4j结合XPath解析xml文件里面的数据
            Element element = (Element) document.selectSingleNode("//bean[@id='"+id+"']");

            // 获得calss属性值
            String aClass = element.attributeValue("class"); //com.wsl.demo02.Dog

            // 获得字节码对象
            Class clazz = Class.forName(aClass);

            // 创建对象
            obj = clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }

}


//抽象类
public interface Animal {

    abstract void eat();

}



public class Test {

    public static void main(String[] args) {

        // 创建对象
        //Animal animal = new Dog();  // 多态【父类引用指向子类对象】

        //【一旦改动就违背了Java的一个原则,开闭原则(已经写好的代码不要修改,你可以扩展其功能)】
        //Animal animal = new Cat();

        /////////////////////////////////////////////////
        Animal animal = (Animal) BeanFactory.getBean("Animal");

        System.out.println(animal);

    }
}

<?xml version="1.0" encoding="UTF-8"?>
<books>
       <book id="01" 出版社="呵呵版社">
            <name>Java编程思想</name>
            <author>James</author>
            <price>98.00</price>
            <body>库存:30</body>
       </book>
    <book id="02" 出版社="哈哈版社">
            <name>JavaEE从入门到精通</name>
            <author>播客</author>
            <price>40.00</price>
            <body>库存:20</body>
    </book>
    <book id="03" 出版社="你好出版社">
            <name>Java开发手册</name>
            <author>阿里巴巴</author>
            <price>15.00</price>
            <body>库存:300</body>
    </book>
</books>



 @Test
    public  void Dom4jXML() throws Exception{
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(new File("D:\\book.xml"));
        Element rootElement = document.getRootElement();
        List<Element> elements = rootElement.elements();
        for (Element element : elements) {
            List<Attribute> attributes = element.attributes();
            for (Attribute attribute : attributes) {
                System.out.println(attribute.getName()+":"+attribute.getText());
            }
            List<Element> elements1 = element.elements();
            for (Element element1 : elements1) {
                System.out.println(element1.getName()+":"+element1.getText());
            }
            System.out.println("========================");
        }
    }

    @Test
    public void Dom4jXPath() throws Exception{
        SAXReader saxReader = new SAXReader() ;
        Document document = saxReader.read(new File("D:\\book.xml"));
        List<Element> list = document.selectNodes("//book");
        Node node = document.selectSingleNode("//book[@id='01']/name");
        System.out.println(node.getText());
        System.out.println("---------------------------------------");
        for (Element element : list) {
            String att1 = element.attributeValue("id");
            String att2 = element.attributeValue("出版社");
            System.out.println("id:"+att1);
            System.out.println("出版社:"+att2);
            String name = element.elementText("name");
            System.out.println("name:"+name);
            String author = element.elementText("author");
            System.out.println("author:"+author);
            String price = element.elementText("price");
            System.out.println("price:"+price);
            String body = element.elementText("body");
            System.out.println("body:"+body);
            System.out.println("========================");

        }

    }
<?xml version="1.0" encoding="UTF-8"?>
<config>
    <class id="001">
        <classname>com.wsl.ze.Person</classname>
        <hubby>hahhh</hubby>
    </class>
</config>


  public static void main(String[] args) throws Exception{

        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(new File("D:\\config.xml"));

        Node node1 = document.selectSingleNode("//class[@id='001']/classname");
        Node node2 = document.selectSingleNode("//class[@id='001']/hubby");

        Class aClass = Class.forName(node1.getText());
        Person person = (Person) aClass.newInstance();
        Method eat = aClass.getMethod("eat");
        eat.invoke(person);
        Method hubby = aClass.getMethod("hubby",String.class);
        hubby.invoke(person,node2.getText());

    }
发布了117 篇原创文章 · 获赞 20 · 访问量 27万+

猜你喜欢

转载自blog.csdn.net/u010581811/article/details/105199834