前面学习了XML 的书写规范,以及XML 的解析方式,今天看一个实例,将XML 用于存储数据。
1、首先,建立XML 文件:
dataBase.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<dataBase>
<student idCard="001">
<name>Tom</name>
<age>25</age>
<score>98</score>
</student>
<student idCard="001">
<name>John</name>
<age>25</age>
<score>98</score>
</student>
</dataBase>
2、建立 domain 类
Student.java
package com.haizhu.xmlUsedAsDataBase.domain;
public class Student {
private String name;
private String idCard;
private String age;
private Double score;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public Double getScore() {
return score;
}
public void setScore(Double score) {
this.score = score;
}
public String getIdCard() {
return idCard;
}
public void setIdCard(String idCard) {
this.idCard = idCard;
}
}
3、因为我们是将数据存储在XML文件中,而解析XML文件,或者将内存中的数据写入XML 文件都需要一些固定的解析格式,我们可以将这些固定的代码抽象出来,写成一个工具方法,这就是
XmlUtils.java
package com.haizhu.xmlUsedAsDataBase.utils;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
public class XmlUtil {
// 根据传入的地址,取到这个 document
public static Document getDocument(String str) throws ParserConfigurationException, SAXException, IOException{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(str);
return document;
}
// 提交添加操作
public static void write2Xml(Document document,String str) throws FileNotFoundException, TransformerException{
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer= factory.newTransformer();
transformer.transform(new DOMSource(document), new StreamResult(new FileOutputStream(str)));
}
}
4、现在我们写具体操作方法:
StudentDao.java
package com.haizhu.xmlUsedAsDataBase.dao;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import com.haizhu.xmlUsedAsDataBase.domain.Student;
import com.haizhu.xmlUsedAsDataBase.exception.StudentNotFoundException;
import com.haizhu.xmlUsedAsDataBase.utils.XmlUtil;
public class StudentDao {
// 指定读取和写入的xml的文件地址
String str = "src/com/haizhu/xmlUsedAsDataBase/dataBase.xml";
public void add(Student s){
try {
// 取得 document
Document document = XmlUtil.getDocument(str);
//取得 Element
Element dataBase = document.getDocumentElement(); // 根节点
Element student_tag = document.createElement("student"); // |——学生节点
Element name = document.createElement("name"); // |————name属性
Element age = document.createElement("age"); // |————age
Element score= document.createElement("score"); // |————score
// 对Element各个属性赋值
student_tag.setAttribute("idCard", s.getIdCard());
name.setTextContent(s.getName());
age.setTextContent(s.getAge());
score.setTextContent(s.getScore().toString());
// 将各个属性添加到 student 对象
student_tag.appendChild(name);
student_tag.appendChild(age);
student_tag.appendChild(score);
// 将这个 student 对象添加到 存储在内存中的 document 中
dataBase.appendChild(student_tag);
// 提交:将内存中的对象写入 xml 文件
XmlUtil.write2Xml(document, str);
System.out.println("添加数据成功!");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 根据idCard 查找 student:先查出所有的student,然后遍历与传入的参数比对,匹配的就封装在一个student对象中
public Student findByIdCard(String idCard){
try {
Document document = XmlUtil.getDocument(str);
// 加载出所有的student
NodeList list = document.getElementsByTagName("student");
// 遍历出每个student
for(int i=0;i<list.getLength();i++){
// 类型转换:将 Node 类型 强制转换为 student 类型
Element student_tag = (Element)list.item(i);
// 是否匹配
if(student_tag.getAttribute("idCard").equals(idCard)){
// 如果是的话将内容封装进一个sutdent对象中
Student s = new Student();
s.setIdCard(idCard);
s.setName(student_tag.getElementsByTagName("name").item(0).getTextContent());
s.setAge(student_tag.getElementsByTagName("age").item(0).getTextContent());
s.setScore(Double.parseDouble(student_tag.getElementsByTagName("score").item(0).getTextContent()));
// 返回这个student 对象
return s;
}
}
return null;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 根据 name 删除:加载出所有的student对象,按照name比对,匹配的就将他删除
public void deleteByName(String name) throws StudentNotFoundException{
try {
Document document = XmlUtil.getDocument(str);
// 加载所有 student
NodeList list = document.getElementsByTagName("name");
// 遍历所有的节点Node,与name比对做准备
for(int i=0;i<list.getLength();i++){
// 强制类型转换,Node 转换为 Element
Element findName = (Element)list.item(i);
// 匹配的话就删除这个对象
if(findName.getTextContent().equals(name)){
// 删除的方法是使用父类节点,然后不调用 removeChild 方法
System.out.println(findName.getParentNode());
findName.getParentNode().getParentNode().removeChild(findName.getParentNode());
// 提交:将内存中的对象写入 xml 文件
XmlUtil.write2Xml(document, str);
System.out.println("删除成功!");
return;
}
}
// 如果查找的这个student不存在,就需要告诉操作者,这里使用自定义异常
throw new StudentNotFoundException(name+"不存在!"); // 自定义编译时异常,抛出
} catch(StudentNotFoundException e){ // 捕捉,不然的话最后一个catch把异常捕捉之后就会转换成运行时异常
throw e; // 抛出的时候要在本方法deleteByName()后面加上 throws StudentNotFoundException
} catch (Exception e) {
throw new RuntimeException(e); // 抛出的运行时异常,就不需要在deleteByName()方法后面加声明了
}
}
}
/**
* 本例子中,最容易忘记的一点:在增加、删除、修改数据的时候,这里数据修改之后一定要调用write2Xml()方法,不然,操作的只是内存中的数据,而没有对xml文件进行修改
* 另外,在增加操作时候,在给各个Element赋值之后,一定要将这些Element之间的关系通过 appendChild() 方法进行操作,不然,只是赋值,但是没有关联到对象节点之中
*/
5、在上面这些个操作方法中,我们自己定义了一个异常类
StudentNotFoundException.java
package com.haizhu.xmlUsedAsDataBase.exception;
public class StudentNotFoundException extends Exception {
private static final long serialVersionUID = 1L;
public StudentNotFoundException() {
}
public StudentNotFoundException(String message) {
super(message);
}
public StudentNotFoundException(Throwable cause) {
super(cause);
}
public StudentNotFoundException(String message, Throwable cause) {
super(message, cause);
}
}
6、方法写好之后,就需要有一个操作入口,调用这些方法:
Main.java
package com.haizhu.xmlUsedAsDataBase.UI;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import com.haizhu.xmlUsedAsDataBase.dao.StudentDao;
import com.haizhu.xmlUsedAsDataBase.domain.Student;
import com.haizhu.xmlUsedAsDataBase.exception.StudentNotFoundException;
public class Main {
public static void main(String[] args) {
System.out.println("根据选项输入字符:");
System.out.println("a:添加学生\rb:删除学生\rc:查找学生");
try {
// 这是系统的编码格式查询
System.getProperty("file.encoding");
// 从键盘接收输入的字符流,但是如何解决乱码的问题?
InputStreamReader isr = new InputStreamReader(System.in);
//
BufferedReader br = new BufferedReader(isr);
String type = br.readLine();
StudentDao dao = new StudentDao();
if("a".equals(type)){
System.out.println("请输入姓名:");
String name = br.readLine();
System.out.println(name);
System.out.println("请输入idCard:");
String idCard = br.readLine();
System.out.println("请输入年龄:");
String age = br.readLine();
System.out.println("请输入成绩:");
String score = br.readLine();
Student s = new Student();
s.setName(name);
s.setIdCard(idCard);
s.setAge(age);
s.setScore(Double.parseDouble(score));
dao.add(s);
}else if("b".equals(type)){
System.out.println("请输入需要删除人的姓名:");
String name = br.readLine();
try {
dao.deleteByName(name);
} catch (StudentNotFoundException e) {
System.out.println("您要删除的人不存在!");
}
}else if("c".equals(type)){
System.out.println("请输入需要查找人的idCard:");
String idCard = br.readLine();
Student s = dao.findByIdCard(idCard);
System.out.println("姓名:"+s.getName()+"、年龄:"+s.getAge()+"、成绩:"+s.getScore());
}else{
System.out.println("请核对选项对应的字符!重新输入!");
}
} catch (IOException e) {
System.out.println("抱歉,出错了!");
e.printStackTrace();
}
}
}
/**
* 后台对于异常的处理,是抛出来丢给调用层,但是在用户view层,不能再抛出异常了,必须进行处理。
*
*/
至此,一个完成的XML操作完成。
代码地址:
点击打开链接