dom4j 是一种解析 XML 文档的开放源代码 XML 框架,本文就来介绍利用它完成学生对象的 CRUD 操作。 dom4j API 包含一个解析 XML 文档的工具,与 W3C DOM API 相比,使用 dom4j 所包含的解析器的好处是 dom4j 拥有本地的 XPath 支持。由于 student.xml 比较简单,我们这里并没有使用 Xpath 。所以我们只需将 dom4j 的 jar 包导入到 classpath 里面即可。好了,准备就绪,我们开始吧!
1. 做一个 DTO 类 Student
package com.wepull.student.model;
public class Student {
private int id ;
private String name ;
private int 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;
}
}
2. 做一个查询条件类 Cond
package com.wepull.student.model;
/**
* @author leno
* javabean 风格的简单查询条件类
*/
public class Cond {
private String colName ;
private String operation ;
private String colValue ;
public String getColName() {
return colName ;
}
public void setColName(String colName) {
this . colName = colName;
}
public String getOperation() {
return operation ;
}
public void setOperation(String operation) {
this . operation = operation;
}
public String getColValue() {
return colValue ;
}
public void setColValue(String colValue) {
this . colValue = colValue;
}
}
3. 做一个操作学生对象的 DAO 的接口
package com.wepull.student.model;
import java.util.List;
public interface IStudentDAO {
public void insert(Student stu);
public void edit(Student stu);
public void del( int id);
public Student findById( int id);
public int getRecords();
public List<Student> findAll();
public List<Student> findAll( int page, int pageSize);
public List<Student> findAll(List<Cond> cond, int page, int pageSize);
}
4. 做一个操作学生对象的 DAO 的实现类,该类就是重点
package com.wepull.student.model;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
/**
* @author leno
* @version 1.0 操作 student.xml 的 DAO 类 利用 dom4j 对存储在 xml 格式文件上的数据进行 CRUD
*/
public class StudentDAO implements IStudentDAO {
private String xmlPath = "student.xml" ;
private Document doc ;
{
init();
}
public StudentDAO() {
}
public StudentDAO(String xmlPath) {
this . xmlPath = xmlPath;
}
/**
* 初始化工作, xml 文件存在而读取,
* 不存在则按照一定格式在当前工程下创建
*/
public void init() {
File file = new File( xmlPath );
if (file.exists()) {
SAXReader reader = new SAXReader();
try {
doc = reader.read(file);
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
doc = DocumentHelper.createDocument ();
// 使用 addDocType() 方法添加文档类型说明
doc .addDocType( "students" , null , "student.dtd" );
Element root = doc .addElement( "students" );
root.addComment( "student's information!" );
overRideXml();
}
}
public void del( int id) {
Element element = findElementById(id);
if (element != null ) {
doc .getRootElement().remove(element);
overRideXml();
}
}
public void insert(Student stu) {
int currId = getMaxId() + 1;
Element root = doc .getRootElement();
Element student = root.addElement( "student" );
student.addAttribute( "id" , String.valueOf (currId));
Element name = student.addElement( "name" );
name.setText(stu.getName());
Element age = student.addElement( "age" );
age.setText(String.valueOf (stu.getAge()));
overRideXml();
}
public void edit(Student stu) {
int id = stu.getId();
Element element = findElementById(id);
if (element != null ) {
element.element( "name" ).setText(stu.getName());
element.element( "age" ).setText(String.valueOf (stu.getAge()));
overRideXml();
}
}
@SuppressWarnings ( "unchecked" )
public List<Student> findAll() {
List<Student> list = new ArrayList<Student>();
Element root = doc .getRootElement();
Iterator<Element> it = root.elementIterator( "student" );
while (it.hasNext()) {
Element element = it.next();
Student stu = new Student();
stu.setId(Integer.parseInt (element.attributeValue( "id" )));
stu.setName(element.elementText( "name" ));
stu.setAge(Integer.parseInt (element.elementText( "age" )));
list.add(stu);
}
return list;
}
@SuppressWarnings ( "unchecked" )
public List<Student> findAll( int page, int pageSize) {
List<Student> list = new ArrayList<Student>();
Element root = doc .getRootElement();
List<Element> allList = root.elements();
int size = allList.size();
int maxPage = (size + pageSize - 1) / pageSize;
if (size == 0 || page < 1 || page > maxPage) {
return list;
}
int start = (page - 1) * pageSize;
int end = start + pageSize;
if (end > size) {
end = allList.size();
}
List<Element> eleList = allList.subList(start, end);
Iterator<Element> it = eleList.iterator();
while (it.hasNext()) {
Element element = it.next();
Student stu = new Student();
stu.setId(Integer.parseInt (element.attributeValue( "id" )));
stu.setName(element.elementText( "name" ));
stu.setAge(Integer.parseInt (element.elementText( "age" )));
list.add(stu);
}
return list;
}
/**
* 分页并且按照条件查询学生数据 ( 有待加强和优化 )
*/
@SuppressWarnings ( "unchecked" )
public List<Student> findAll(List<Cond> conds, int page, int pageSize) {
List<Student> list = new ArrayList<Student>();
Element root = doc .getRootElement();
List<Element> allList = new ArrayList<Element>();
Iterator<Element> allIt = root.elementIterator();
while (allIt.hasNext()) {
Element element = allIt.next();
String id = element.attributeValue( "id" );
String name = element.elementText( "name" );
String age = element.elementText( "age" );
for ( int i = 0; i < conds.size(); i++) {
Cond cond = conds.get(i);
String colName = cond.getColName();
String operation = cond.getOperation();
String colValue = cond.getColValue();
if ( "id" .equals(colName)) {
if (operation.equals( "=" )) {
if (!id.equals(colValue)) {
break ;
}
}
} else if ( "name" .equals(colName)) {
if (operation.equals( "=" )) {
if (!name.equals(colValue)) {
break ;
}
} else if (operation.equals( "like" )) {
if (!name.contains(colValue)) {
break ;
}
}
} else if ( "age" .equals(colName)) {
if (operation.equals( "=" )) {
if (!age.equals(colValue)) {
break ;
}
}
}
}
allList.add(element);
}
int size = allList.size();
int maxPage = (size + pageSize - 1) / pageSize;
if (size == 0 || page < 1 || page > maxPage) {
return list;
}
int start = (page - 1) * pageSize;
int end = start + pageSize;
if (end > size) {
end = allList.size();
}
List<Element> eleList = allList.subList(start, end);
Iterator<Element> it = eleList.iterator();
while (it.hasNext()) {
Element element = it.next();
Student stu = new Student();
stu.setId(Integer.parseInt (element.attributeValue( "id" )));
stu.setName(element.elementText( "name" ));
stu.setAge(Integer.parseInt (element.elementText( "age" )));
list.add(stu);
}
return list;
}
public Student findById( int id) {
Student stu = null ;
Element element = findElementById(id);
if (element != null ) {
stu = new Student();
stu.setId(id);
stu.setName(element.elementText( "name" ));
stu.setAge(Integer.parseInt (element.elementText( "age" )));
}
return stu;
}
public int getRecords() {
return doc .getRootElement().elements().size();
}
@SuppressWarnings ( "unchecked" )
private Element findElementById( int id) {
Iterator<Element> it = doc .getRootElement().elementIterator( "student" );
while (it.hasNext()) {
Element element = it.next();
if (String.valueOf (id).equals(element.attributeValue( "id" ))) {
return element;
}
}
return null ;
}
@SuppressWarnings ( "unchecked" )
private int getMaxId() {
int maxId = 0;
Element root = doc .getRootElement();
Iterator<Element> it = root.elementIterator( "student" );
while (it.hasNext()) {
Element element = (Element) it.next();
String id = element.attributeValue( "id" );
if (maxId < Integer.parseInt (id)) {
maxId = Integer.parseInt (id);
}
}
System. out .println( "maxId" + maxId);
return maxId;
}
/**
* 将修改后的 Document 对象写回到 xml 文件中
*/
private void overRideXml() {
/** 格式化输出 , 类型 IE 浏览一样 */
XMLWriter writer = null ;
try {
writer = new XMLWriter( new FileOutputStream( xmlPath ), OutputFormat
.createPrettyPrint ());
writer.write( doc );
writer.close();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
IStudentDAO dao = new StudentDAO();
// System.out.println(dao.getRecords());
// for (int i = 0; i < 40; i++) {
// Student stu = new Student();
// //stu.setId(2);
// stu.setName("www");
// stu.setAge(233);
// dao.insert(stu);
// }
List<Cond> conds = new ArrayList<Cond>();
for ( int i = 0; i < 1; i++) {
Cond cond = new Cond();
cond.setColName( "name" );
cond.setOperation( "like" );
cond.setColValue( "1" );
conds.add(cond);
}
List<Student> list = dao.findAll(conds, 1, 20);
Iterator<Student> it = list.iterator();
while (it.hasNext()) {
Student stu = it.next();
System. out .println(stu.getId() + " " + stu.getName());
}
}
}
5. 将如下 student.dtd 文件放在当前工程目录下
<!ELEMENT students ( student * ) >
<!ELEMENT student ( name , age ) >
<!ATTLIST student id CDATA #IMPLIED >
<!ELEMENT name (#PCDATA) >
<!ELEMENT age (#PCDATA) >
呵呵,我们的工作到此就完成了,最核心的代码在 StudentDAO 里面。大家看到,和我们平时写的 DAO 有很大不同,我们这里的 StudentDAO 就是对一份 XML 文件上的节点进行增删查改。我们还使用了一个接口 IStudentDAO ,这样我们就可以提供诸如 jdbc 访问数据库的 DAO,hibernate 访问数据库的 DAO 等多种数据访问的实现,也就是说,为了更加松散的耦合,我们提倡大家面向接口编程。大家边跑这个例子边认真体会一下 dom4j 的方便之处,当大家下次没有数据库时,再也不会愁眉苦脸,也就可以用 xml 文件来完成数据的存储啦。