利用DOM实现对XML节点的增、删、改、查
程序员文章站
2022-05-03 15:58:23
...
首先介绍一下什么是DOM和XML
DOM英文全称是Document Object Model,中文是文档对象模型,它相当于一个针对HTML和XML文档的一个API,通过使用DOM我们可以去改变文档。
XML英文全称是Extensible Markup Language,中文名称是可扩展标记语言,XML的主要作用是可以持久化存储数据,在这个基础上可以实现数据的交换,它还有一个作用是在框架中进行数据配置,这里主要利用一下XML持久化存储数据的作用。
下面做一个针对XML文件数据的增、删、改、查操作
第一步:我们新建一个XML文件
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<students>
<student>
<id>1</id>
<name>王五</name>
<age>23</age>
</student>
<student>
<id>2</id>
<name>张三</name>
<age>20</age>
</student>
<student>
<id>3</id>
<name>李四</name>
<age>20</age>
</student>
</students>
在这里我们创建学生的xml,里面设置id,name,age三个字段。插入3条数据。
第二步:根据XML文档的数据类型创建entity实体
public class Student {
private int id;
private String name;
private int age;
public Student() {
super();
}
public Student(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
学生实体中,我们生成它的get和set方法,无参和有参构造方法,并且重写了toString方法,方便我们在随后的操作中输出数据。
第三步:创建针对XML文件操作的service接口
import java.util.List;
import entity.Student;
public interface StudentService {
public boolean add(Student stu);//添加学生
public boolean update(int id,int age);//更新学生
public boolean delete(int id);//根据ID删除学生
public boolean exist(int id);//根据ID判断学生是否存在
public List<Student> getAll();//获得XML文件中所有的学生节点
}
生成student接口,在这里封装好准备要写的具体业务逻辑操作。
第四步:创建serviceImpl实现接口,在这个写具体业务操作
public class StudentServiceImpl implements StudentService {
//XML路径
static String filePath = "src/xml/student.xml";
@Override
public boolean add(Student stu) {
Document doc = getDoc();
if(doc == null){
System.out.println("XML文件不存在");
return false;
}
Node root = doc.getElementsByTagName("students").item(0);
Element stuNode = doc.createElement("student");
Element id = doc.createElement("id");
Element name = doc.createElement("name");
Element age = doc.createElement("age");
if(exist(stu.getId())){
System.out.println("此ID已存在");
return false;
}else{
//添加节点
root.appendChild(stuNode);
stuNode.appendChild(id);
stuNode.appendChild(name);
stuNode.appendChild(age);
//设置节点的值
id.setTextContent(String.valueOf(stu.getId()));
name.setTextContent(stu.getName());
age.setTextContent(String.valueOf(stu.getAge()));
inputXML(doc);
}
return true;
}
@Override
public boolean update(int id, int age) {
Document doc = getDoc();
if(doc == null){
System.out.println("XML文件不存在");
return false;
}
if(exist(id)){
NodeList stus = doc.getElementsByTagName("student");
for (int i = 0; i < stus.getLength(); i++) {
NodeList stuField = stus.item(i).getChildNodes();
boolean isStu = false;
for (int j = 0; j < stuField.getLength(); j++) {
String key = stuField.item(j).getNodeName();
String value = stuField.item(j).getTextContent();
if("id".equals(key) && value.equals(String.valueOf(id))){
isStu = true;
}
if("age".equals(key) && isStu){
stuField.item(j).setTextContent(String.valueOf(age));
}
}
}
inputXML(doc);
}else{
System.out.println("此ID不存在");
return false;
}
return true;
}
@Override
public boolean delete(int id) {
Document doc = getDoc();
if(doc == null){
System.out.println("XML文件不存在");
return false;
}
if(!exist(id)){
System.out.println("此ID不存在");
return false;
}else{
Node root = doc.getElementsByTagName("students").item(0);
NodeList stuID = doc.getElementsByTagName("id");
for (int i = 0; i < stuID.getLength(); i++) {
String value = stuID.item(i).getTextContent();
if(value.equals(String.valueOf(id))){
root.removeChild(stuID.item(i).getParentNode());
i--;//注意,若不进行i--操作,连续的两个重复ID,后面的那个将不会被删除
}
}
inputXML(doc);
}
return true;
}
@Override
public boolean exist(int id) {
Document doc = getDoc();
if(doc == null){
System.out.println("XML文件不存在");
return false;
}
NodeList stus = doc.getElementsByTagName("student");
for (int i = 0; i < stus.getLength(); i++) {
NodeList stuField = stus.item(i).getChildNodes();
Student stu = new Student();
for (int j = 0; j < stuField.getLength(); j++) {
String key = stuField.item(j).getNodeName();
String value = stuField.item(j).getTextContent();
if("id".equals(key) && value.equals(String.valueOf(id))){
return true;
}
}
}
return false;
}
@Override
public List<Student> getAll() {
List<Student> list = new ArrayList<Student>();
Document doc = getDoc();
if(doc == null){
System.out.println("XML文件不存在");
return null;
}
NodeList stus = doc.getElementsByTagName("student");
for (int i = 0; i < stus.getLength(); i++) {
NodeList stuField = stus.item(i).getChildNodes();
Student stu = new Student();
for (int j = 0; j < stuField.getLength(); j++) {
String key = stuField.item(j).getNodeName();
String value = stuField.item(j).getTextContent();
if("id".equals(key)){
stu.setId(Integer.parseInt(value));
}
if("name".equals(key)){
stu.setName(value);
}
if("age".equals(key)){
stu.setAge(Integer.parseInt(value));
}
}
list.add(stu);
}
return list;
}
/**
* 返回Document对象
* @return
*/
private Document getDoc(){
try {
//创建转换器工厂
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
//创建转换器对象
DocumentBuilder db = dbf.newDocumentBuilder();
//创建文档对象
Document doc = db.parse(filePath);
return doc;
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 将修改好的文件更新替换原来的XML文件
* @param filePath
*/
private void inputXML(Document doc){
TransformerFactory tff = TransformerFactory.newInstance();
try {
Transformer tf = tff.newTransformer();
tf.transform(new DOMSource(doc), new StreamResult(new File(filePath)));
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
}
}
第五步:导入Junit4测试,完成所有操作
public class TestStudent {
StudentService stuImpl = new StudentServiceImpl();
@Test
public void testAdd(){
if(stuImpl.add(new Student(3, "张三", 20))){
System.out.println("添加成功");
}else{
System.out.println("添加失败");
}
}
@Test
public void testUpdate(){
if(stuImpl.update(2, 20)){
System.out.println("修改成功");
}else{
System.out.println("修改失败");
}
}
@Test
public void testDelete(){
if(stuImpl.delete(2)){
System.out.println("删除成功");
}else{
System.out.println("删除失败");
}
}
@Test
public void testGetAll(){
List<Student> list = stuImpl.getAll();
for (Student student : list) {
System.out.println(student);
}
}
}
总结
操作DOM总体来说基本实现了对XML文件的解析,但美中不足的是无法插入外部引用DTD或者内部的DTD,因为每次进行操作以后,都会生成一个新的xml文件去覆盖以前的xml文件,楼主查了查资料,发现好像是DOM无法直接在头部插入语句,所以这是学习过程中的一大问题。
还有问题是出现在删除操作中,出现的问题是每次删除以后,不判断后面那一个,如果有两个重复的ID,那么后面那一个将不会被删除,原因是进行删除以后,节点的个数就会发生改变,解决这个问题的方法时在每次成功删除以后,让循环的变量i减一,保证数组的每一个都会被遍历到。
楼主还是小白级别,如果代码中间哪里有问题,欢迎大家在评论区指出,大家一起进步。嘻嘻嘻