Java学习笔记@XML文档、解析、检索

笔者:unirithe

日期:11/13/2021

XML

概述

XMl是可扩展标记语言(eXtensible Markup Language) 的缩写,是一种数据表示格式,可以描述非常复杂的数据结构,常用于传输和存储数据

例如:

<?xml version="1.0" encoding="UTF-8"?>
<data>
	
</data>

XML的作用

  • 用于进行存储和传输数据
  • 作为软件的配置文件

XML的特点

  • 纯文本,默认使用UTF8编码
  • 可嵌套

XML的应用场景

  • 作为消息进行网络传输
  • 作为配置文件用于存储系统信息

使用规范

XML语法规范

  • 文件后缀使用.xml
  • 文档声明必须是第一行 ,如:<? xml version="1.0" encoding="UTF-8" ?>

XML的标签(即元素)规范

  • 标签由一对尖括号和合法标识符组成,比如<name></name>,XML必须存在一个根标签,有且只能有一个

  • 普通标签必须成对出现

  • 特殊的标签可以不成对,但必须有结束的标记,如 <br/>

  • 标签中可定义属性,属性和标签名以空格隔开,属性值必须用引号引起来

  • 标签嵌套要符合逻辑,如:

    <user id = "1">
    	<name>unirithe</name>
    </user>
    

XML注释 (和HTML注释方式一样)

<!-- 注释内容 -->

XML转义字符

符号 表示方法
< 小于 &lt;
> 大于 &gt;
& 和 &amp;
`单引号 &apos;
"双引号 &quot;

除了使用转义字符外, XML文件中可定义 CDATA区 <![CDATA[...任意内容...]]

XML 文档约束

文档约束:限定XML文件中的标签以及属性编写格式,主要有两种DTD和Schema

DTD约束

约束的文件后缀为.dtd

范例: (+号表示至少一个以上)

<!ELEMENT Schall(student+)>
<!ELEMENT student(name, sex)>
<!ELEMENT name(#PCDATA)>
<!ELEMENT sex(#PCDATA)>

使用方法

<? xml version="1.0" encoding="UTF-8" ?>

<School>
	<student>
        <name>unirithe</name>
        <sex>man</sex>
 	</student>	
    
    <student>
        <name>lucky</name>
        <sex>woman</sex>
 	</student>	
</School>

存在问题:无法约束具体的数据类型

Schema约束

作用:

  • 可约束XML的数据类型
  • 本身也是XML文件,受到其他约束文件的要求
  • 后缀使用.xsd
<?xml version="1.0" encoding="UTF-8" ?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://www.itcast.cn"
        elementFormDefault="qualified">
    <!-- targetNamespace 申明约束文档的位置 -->
    <element name="School">
        <complexType>
            <sequence maxOccurs="unbounded"> <!-- 设置子元素为任意多个 -->
                <element name="Student">
                    <complexType>
                        <sequence>
                            <element name = "name" type="string"/>
                            <element name = "sex" type ="string"/>
                            <element name = "age" type="int"/>
                        </sequence>
                    </complexType>
                </element>
            </sequence>
        </complexType>
    </element>
</schema>

使用

<?xml version="1.0" encoding="UTF-8" ?>
<School xmlns="http://www.itcast.cn"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.itcast.cn data.xsd">
    <Student>
        <name>unitihe</name>
        <sex>man</sex>
        <age>21</age>
    </Student>
</School>

一般Schema约束都可以直接采取网络获取的方式,即配置xmlns属性,而无需自己编写

XML 解析技术

两大技术:SAX解析、DOM解析

DOM常见解析工具

名称 描述
JAXP SUN公司提供的一套XML的解析API
JDOM 基于树型结构的开源项目,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作
*dom4j 是JDOM的升级品,用来读写XML文件。具有性能优异、功能强大和极容易使用的特点,它的性能超过SUN公司官方的DOM技术,同时也是一个开放源代码的软件,Hibernate就用它读写配置文件
jsoup 功能强大DOM方式的XML解析开发包,尤其是对HTML解析更方便

常用解析工具:Dom4j

image

Document对象:整个XML文档

Node 对象

  • Element对象:标签

  • Atrribute对象:属性

  • Text对象:文本内容

Dom4j 快速入门

安装与配置

使用Dom4j只需要下载对应的驱动jar包即可在Java类中使用

Dem4j官方网址

适用于JDK8+版本的Dom4j-2.1.3版本下载地址

https://github.com/dom4j/dom4j/releases/download/version-2.1.3/dom4j-2.1.3.jar

下载完毕后导入到IDEA的项目中即可

另外,还可下载该版本对应的指导文档,下载地址:点这

Dom4j 的使用

Dom4j解析XML得到Document对象

SAXReader类

构造器/方法 描述
public SAXReader() 创建Dom4J的解析器对象
Document read(String url) 加载XML文件称为Document对象

Document类

方法 描述
Element getRootElement() 获得根元素对象

User.xml

<?xml version="1.0" encoding="UTF-8" ?>
<School >
    <Student id="1">
        <name>unitihe</name>
        <sex>man</sex>
    </Student>

    <Student id="2">
        <name>lucky</name>
        <sex>woman</sex>
    </Student>
</School>
package com.uni;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.junit.Test;

import java.io.InputStream;
public class Dom4jDemo {
    @Test
    public void test() throws Exception {
        SAXReader saxReader = new SAXReader();
        InputStream is = Dom4jDemo.class.getResourceAsStream("/userSchema.xml");
        Document document = saxReader.read(is);
        Element root = document.getRootElement();
        System.out.println(root);
    }
}

解析元素、属性文本的常用API

方法名 描述
List<Element> elements() 得到当前元素下所有子元素
List<Element>elements(String name) 得到当前元素下指定名字的子元素返回集合
Element element(String name) 得到当前元素下指定名字的子元素,如果有多个则返回第一个
String getName() 得到元素名字
String attributeValue(String name) 通过属性名直接得到属性值
String elementType(子元素名) 得到指定名称的子元素的文本
String getText() 得到文本

范例:获取所有名为Student的一级子元素对象

List<Element> sons = root.elements("Student");

范例:获取第一个名为Student的一级子元素对象

Element userEle = root.element("Student");

范例:输出所有一级子元素的name值

List<Element> userEle = root.elements("Student");
for (Element element : userEle)
    System.out.println(element.elementText("name"))

范例:根据元素获取属性值

List<Element> userEle = root.elements("Student");
for (Element element : userEle) {
	Attribute idAttr = element.attribute("id");
	System.out.println(idAttr.getName() + " -> " + idAttr.getValue());
}

更简便的方法:

System.out.println(element.attributeValue("id"));

XML 解析 案例

编写Java程序实现对XML文件进行解析,并创建对象存储内容

User.xml

<?xml version="1.0" encoding="UTF-8" ?>
<School >
    <Student id="1">
        <name>unitihe</name>
        <sex>man</sex>
    </Student>

    <Student id="2">
        <name>lucky</name>
        <sex>woman</sex>
    </Student>
</School>
class Student{
    private int id;
    private String name, sex;
    public Student(){}
    public Student(int id, String name, String sex) {
        this.id = id;
        this.name = name;
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }
}
public class Dom4jDemo {
    @Test
    public void parseXMLData() throws Exception {
        SAXReader saxReader = new SAXReader();
        InputStream is = Dom4jDemo.class.getResourceAsStream("/user.xml");
        Document document = saxReader.read(is);
        Element root = document.getRootElement();

        List<Element> stuEle = root.elements("Student");

        List<Student> students = new ArrayList<>();
        for (Element stu : stuEle) {
            int id = Integer.valueOf(stu.attributeValue("id"));
            String name = stu.elementText("name");
            String sex = stu.elementText("sex");
            students.add(new Student(id, name, sex));
        }
        for (Student student : students) {
            System.out.println(student);
        }
    }
}

运行结果

Student{id=1, name='unitihe', sex='man'}
Student

XML 检索 XPath技术

Dom4j是先对XMl文件进行解析,然后再寻找数据,而XPath技术更适合 信息检索

XPath的特点

  • 基于Dom4j开发的

  • 提供了独树一帜的路径思想,更优雅高效

  • 使用路径表达式来定位XMl文档中元素节点或属性节点

Xpath 快速入门

在使用XPath时,除了导入Dom4j.jar包以外,还需要导入jaxen-*.jar 下载点这

实现步骤

  • 导入jar包 Dom4j 和 jaxen
  • 通过 dom4j的SAXReader 获取 Document 对象
  • 利用XPath提供的API,结合XPath的语法完成选取XML文档元素节点进行解析操作

Document中与Xpath相关的API如下:

方法名 描述
Node selectSingleNode("表达式") 获取符合表达式的唯一元素
List<Node> selectNodes("表达式") 获取符合表达式的元素结合

Xpath 的四大检索方案

  • 绝对路径
  • 相对路径
  • 全文检索
  • 属性查找

绝对路径 检索

采用绝对路径获取从根节点开始逐层的查找

方法名 描述
/根元素/子元素/孙元素 从根元素开始,一级一级向下查找,不能跨级
package com.uni;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.junit.Test;
import java.util.List;

public class XPathDemo {
    @Test
    public void test() throws Exception {
        SAXReader saxReader= new SAXReader();

        Document document = saxReader.read(XPathDemo.class.getResourceAsStream("/user.xml"));
        List<Node> nameNodes = document.selectNodes("/School/Student/name");
        for (Node nameNode : nameNodes) {
            Element nameEle = (Element) nameNode;
            System.out.println(nameEle.getText());
        }
    }
}

相对路径 检索

@Test
public void test() throws Exception {
    SAXReader saxReader= new SAXReader();
    Document document = saxReader.read(XPathDemo.class.getResourceAsStream("/user.xml"));
    Element root = document.getRootElement();
	List<Node> nameNodes = root.selectNodes("./Student/name");
	for (Node nameNode : nameNodes) {
		Element nameEle = (Element) nameNode;
		System.out.println(nameEle.getText());
	}
}

全文检索

List<Node> nameNodes = document.selectNodes("//name");
// 相同效果
List<Node> nameNodes = document.selectNodes("//Student/name");

属性检索

  • @属性名称
  • 元素[@属性名称]
  • 元素[@属性名称=值]

范例:@属性名称 检索

SAXReader saxReader= new SAXReader();

Document document = saxReader.read(XPathDemo.class.getResourceAsStream("/user.xml"));

Element root = document.getRootElement();

List<Node> nodes= document.selectNodes("//@id");
// 在这个案例里 @id 效果等同于Student[@id];

for (Node node : nodes) {
	Attribute attr = (Attribute) node;
	System.out.println(attr.getName() +  " -> " + attr.getValue());
}

范例:元素[@属性名称] 检索

List<Node> nodes= document.selectNodes("//Student[@id]");
for (Node node : nodes) {
    Element ele = (Element) node;
    System.out.println(ele.elementText("name"));
}
posted @ 2021-11-13 11:49  Unirithe  阅读(167)  评论(0)    收藏  举报