XML
什么是xml
(Extensible Markup Language)可扩展标记语言,同为标记语言,语言形式与HTML一样,即标签形式
test.xml
<?xml version="1.0" encoding="UTF-8"?>
<books>
<book id="book01">
<name>三国演义</name>
<author>罗贯中</author>
<price>50</price>
</book>
</books>
里面的标签随便定义,非常灵活但不可控,所以我们要学习有效的xml
###什么是有效的xml
格式必须是良好的
使用DTD和XSD定义语义约束
xml练习
使用xml描述下表中的学生成绩信息,xml文件名为scores.xml
ID | NAME | GRADE | COURSE |
---|---|---|---|
1 | 张三 | 98 | java |
2 | 李四 | 66 | mysql |
如果没有约束,不同的人会写出不一样的代码,这样的xml是无效的
DTD
全称document type definition,作用是约束文档格式,保证xml是有效性,它有两种形式
内部DTD
<!DOCTYPE 根元素 [元素声明]>
<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
这是w3school中给我们的示例
我们照猫画虎写一个
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE scores [
<!ELEMENT scores (student*) >
<!ELEMENT student (name, course, grade) >
<!ELEMENT name (#PCDATA) >
<!ELEMENT course (#PCDATA) >
<!ELEMENT grade (#PCDATA) >
<!ATTLIST student id CDATA "0" #REQUIRED>
]>
<scores>
<student id="1">
<name>张三</name>
<course>java</course>
<grade>98</grade>
</student>
<student id="2">
<name>李四</name>
<course>mysql</course>
<grade>66</grade>
</student>
</scores>
其中,涉及到数量词
* 表示任意多个
+ 表示至少一次
? 表示0次或1次
不加符号表示必须且只能出现1次
属性声明方法
属性类型:CDATA(character data),表示字符数据
默认值:#REQUIRED 表示必须包含,#IMPLIED表示非必须包含
#PCDATA 表示不能嵌套标签了
外部DTD
<!DOCTYPE 根元素 SYSTEM "文件名">
scores.dtd
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT scores (student*) >
<!ELEMENT student (name, course, grade) >
<!ELEMENT name (#PCDATA) >
<!ELEMENT course (#PCDATA) >
<!ELEMENT grade (#PCDATA) >
<!ATTLIST student id CDATA #REQUIRED>
test.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE scores SYSTEM "scores.dtd">
<scores>
<!-- 在写标签时会有提示 -->
</scores>
注意在scores.dtd
中的空格不能缺,否则无效
XSD
XML Schema,它是DTD的替代者、升级版,通常是不需要开发人员自己编写的,这里不做讲解。
XML解析技术
对xml文件的操作,包括创建xml,以及增删改查,主要包含以下4种解析技术
- DOM:基于xml树结构,比较耗资源,适用于多次访问XML(是SUN官方提供的解析方式)
- SAX:基于事件,消耗资源小,适用于数据量较大的XML(“民间”解析方式)
- JDOM:开源,比DOM快,JDOM仅适用具体类而不使用接口
- DOM4J:开源,非常优秀的Java XML API,性能优异,功能强大,使用接口而不是实现类
其中DOM和SAX都是原始解析方式,需要编程者编写大量的原生代码,所以出现了JDOM,JDOM提供了很多类和方法来解析xml
而今天的主角是DOM4J,它也开源免费,它是JDOM的升级版,优秀且强大,而且开源免费,不用它用谁?
DOM4J解析XML
读取xml
读写XML文档主要依赖于org.dom4j.io包,有DOMReader和SAXReader两种方式。因为利用了相同的接口,它们的调用方式是一样的。
依赖下载地址https://mvnrepository.com/artifact/dom4j/dom4j/1.6.1
package org.neuedu;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.File;
import java.util.Iterator;
public class XmlParseDemo {
public static void main(String[] args) throws DocumentException {
// 创建 saxReader 对象 用于读取 xml文件
SAXReader saxReader = new SAXReader();
// 创建 文件对象 ,被去读取的对象
File file = new File("src/student.xml");
if (file.exists()) {
// 解析 xml内容
Document document = saxReader.read(file);
// 获取根元素
Element rootElement = document.getRootElement();
// 得到根元素内容迭代器
Iterator<Element> iterator = rootElement.elementIterator();//iter迭代器对象,可以用它来数了
while (iterator.hasNext()){//先往左数,如果有东西就执行{}里的语句
// 获取子元素
Element student = iterator.next();//数到什么就拿出来
// 打印子元素标签名字
// System.out.println(student.getName());
// 获取元素属性
Attribute id = student.attribute("id");
// 打印属性名和值
System.out.println(id.getName()+","+id.getValue());
// 获取子元素的子元素
Element name = student.element("name");
Element age = student.element("age");
Element books = student.element("books");
// 打印名字和内容
// System.out.println(name.getName()+","+name.getText());
// System.out.println(age.getName()+","+age.getText());
// System.out.println(books.getName()+","+books.getText());
/*获取元素中的元素*/
Iterator<Element> iterator1 = books.elementIterator();
while (iterator1.hasNext()){
Element book = iterator1.next();
Element bookname = book.element("bookname");
Element author = book.element("author");
System.out.println(bookname.getText());
System.out.println(author.getText());
}
}
}else {
System.out.println("文件不存在");
}
}
}
关键点:得到Document对象,然后一路迭代即可
写xml
package org.neuedu;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class XmlWriteDemo01 {
public static void main(String[] args) throws IOException {
// DocumentHelper生成Document对象
Document document = DocumentHelper.createDocument();
// 添加并获取根元素
Element root = document.addElement("books");
// 创建元素
Element book1 = root.addElement("book");
// 添加属性
book1.addAttribute("id", "1");
// 为book添加子元素
Element name = book1.addElement("name");
Element author = book1.addElement("author");
Element price = book1.addElement("price");
// 添加文本
name.addText("三体");
author.addText("刘慈欣");
price.addText("60");
// 将 doc 写入一个 xml文件
Writer writer = new FileWriter(new File("src/book.xml"));
document.write(writer);
writer.close();
}
}
上述代码,会发现内容全部输出到一行,如果需要格式良好的输出
package org.neuedu;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import java.io.*;
public class XmlWriteDemo {
public static void main(String[] args) throws IOException {
// 利用 DocumentHelper 创建 Document 对象
Document document = DocumentHelper.createDocument();
// 添加 books 根节点
Element root = document.addElement("books");
// 添加 子节点book
Element book = root.addElement("book");
// 为 book 添加 id属性
book.addAttribute("id","1");
// 添加 子节点 author name price
Element author = book.addElement("author");
Element name = book.addElement("name");
Element price = book.addElement("price");
author.addText("java");
name.addText("tom");
price.addText("100");
// --------------------------------格式不是很良好
// 输出成 xml
// File file = new File("E:\\books.xml");
// Writer writer = new FileWriter(file);
// document.write(writer);
// // 关闭
// writer.close();
// -------------------------------
File file = new File("book1.xml");
Writer writer = new FileWriter(file);
OutputFormat outputFormat = OutputFormat.createPrettyPrint();
XMLWriter xmlWriter = new XMLWriter(writer,outputFormat);
xmlWriter.write(document);
xmlWriter.close();
}
}
课堂练习:备份数据
JPA和xml
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
创建数据库
建实体类
package org.neuedu.xmlpersistense.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity(name = "tb_book")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private String author;
private Double price;
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
", author='" + author + '\'' +
", price=" + price +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
}
application.properties
配置文件
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://localhost:3306/xml01?useSSL=true&userUniCode=true&characterEncoding=UTF-8
spring.datasource.password=root
spring.datasource.username=root
# 是否打印sql
spring.jpa.show-sql=true
# 指定数据库类型
spring.jpa.database=mysql
spring.jpa.database-platform=mysql
# 每次运行时检查表和实体类是否一样,不一样就更新
spring.jpa.hibernate.ddl-auto=update
# 指定方言,否则数据库引擎默认不是Innodb(engine=InnoDB)
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57Dialect
测试
package org.neuedu.xmltest;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.junit.jupiter.api.Test;
import org.neuedu.xmltest.dao.BookDao;
import org.neuedu.xmltest.model.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.List;
@SpringBootTest
class XmltestApplicationTests {
@Autowired
BookDao bookDao;
@Test
void add() {
Book book1 = new Book();
book1.setName("java");
book1.setAuthor("tom");
book1.setPrice(56);
Book book2 = new Book();
book2.setName("c++");
book2.setAuthor("bob");
book2.setPrice(70);
bookDao.saveAndFlush(book1);
bookDao.saveAndFlush(book2);
}
@Test
void xmltest() throws IOException {
List<Book> bookList = bookDao.findAll();
Document document = DocumentHelper.createDocument();
Element books = document.addElement("books");
for (Book book : bookList) {
Element bookNode = books.addElement("book");
bookNode.addAttribute("id",book.getId()+"");
Element name = bookNode.addElement("name");
name.addText(book.getName());
Element author = bookNode.addElement("author");
author.addText(book.getAuthor());
Element price = bookNode.addText("price");
price.addText(book.getPrice()+"");
}
File file = new File("book.xml");
Writer writer = new FileWriter(file);
OutputFormat outputFormat = OutputFormat.createPrettyPrint();
XMLWriter xmlWriter = new XMLWriter(writer,outputFormat);
xmlWriter.write(document);
xmlWriter.close();
}
}
Element author = bookNode.addElement("author");
author.addText(book.getAuthor());
Element price = bookNode.addText("price");
price.addText(book.getPrice()+"");
}
File file = new File("book.xml");
Writer writer = new FileWriter(file);
OutputFormat outputFormat = OutputFormat.createPrettyPrint();
XMLWriter xmlWriter = new XMLWriter(writer,outputFormat);
xmlWriter.write(document);
xmlWriter.close();
}
}