去年曾经写了一些空间日志功能的代码,当初实现的方式是数据库保存一些简单的信息,日志内容存在XML文件中,使用文件服务器减轻数据库的负担。
这就不可避免的使用了对xml文件的解析,DOM4J解析和SAX解析,都知道SAX每次都会去读取整个XML文件,对于大文件来说,性能上DOM4J优于SAX解析,所以我选择的是DOM4J的API.
虽然最后整个项目进行了些调整,项目最终也没能上线,但是对于我来说那些已经不重要了。
XmlUtil:
/**
* 以DOM4J默认的SAX解析器解析
*
* @author yiyaqin
* @date 2010-9-2 下午08:01:46
* @param path
* @return
* @throws DocumentException
*/
public static org.dom4j.Document parse(String path) throws DocumentException {
// 以DOM4J默认的SAX解析器解析
SAXReader reader = new SAXReader();
// read函数的形参可以是url 也可以是 File类型,也可以是STRING类型的相对或绝对路径
org.dom4j.Document document = reader.read(path);
return document;
}
/**
* 更新后写入文件
*
* @author yiyaqin
* @date 2010-9-2 下午08:04:19
* @param doc
* @param path
* @throws IOException
*/
public static void write(org.dom4j.Document doc, String path) throws IOException {
// 格式化 XML文件
OutputFormat format = OutputFormat.createPrettyPrint();
// 创建输出流
XMLWriter output = new XMLWriter(new FileOutputStream(new File(path)),
format);
output.write(doc);
if (null != output)
output.close();
}
//创建XML文档
public void createXML(String path) throws Exception{
if(StringUtils.isBlank(path)){
return;
}
//建立一个文档实例
Document document = DocumentHelper.createDocument();
//创建根元素
Element catalogElement = document.addElement("root");
//根元素下面添加content元素
catalogElement.addElement("content");
//根元素下面添加comments元素
Element ele = catalogElement.addElement("comments");
//comments元素添加属性
ele.attributeValue("count", String.valueOf(0));
// 输出格式化
XmlUtil.write(document, path);
}
根据ID删除某个节点:
public void deleteAlbum(String path, String albumID) throws Exception {
if (StringUtils.isBlank(path) || StringUtils.isBlank(albumID)) {
return;
}
//获取整个XML文档
Document doc = XmlUtil.parse(path);
//获取跟节点
Element root = doc.getRootElement();
//根据节点获取所有节点下的属性ID
List<Node> list = doc.selectNodes("/items/item/@id");
for (Node node : list) {
if (node.getText().equals(albumID)) {
root.remove(node.getParent());//移除某个节点
}
}
//重新写入XMl
XmlUtil.write(doc, path);
}
根据ID修改某个节点元素:
public void modifyAlbum(String path, AlbumInfoDTO album) throws Exception {
if (StringUtils.isBlank(path) || null == album) {
return;
}
// 获取整个XML文档
Document doc = XmlUtil.parse(path);
List<Node> list = doc.selectNodes("/items/item/@id");
for (Node node : list) {
if (node.getText().equals(album.getId())) {
Element ele = node.getParent();
// 添加属性
ele.addAttribute("name", album.getName());
// 添加CADA节点
ele.element("content").node(0).setText(album.getQuestion());
// 添加普通的文本节点
ele.element("text").setText("xxxx");
}
}
XmlUtil.write(doc, path);
}
对于修改曾经遇到过一点问题,对于CDATA文本节点的修改我最开始直接用的
ele.element("text").setText("xxxx");
结果可想而知了,后来才知道原来CDATA的节点元素是由一个CDATA节点和一个文本节点构成的。从添加 elemen.element("content").addCDATA(“data”);来看就知道,她是再元素的基础上在添加CDATA节点,然后再CDATA加上文本内容。
获取所有数据:
public List<AlbumInfoDTO> readAllAlbum(String path) throws Exception {
if (StringUtils.isBlank(path)) {
return null;
}
List<AlbumInfoDTO> albumList = null;
Document doc = XmlUtil.parse(path);
Element root = doc.getRootElement();
//获取根节点下所有的元素
List<Element> itemList = root.elements();
if (itemList.size() != 0) {
albumList = new ArrayList<AlbumInfoDTO>();
// 读取所有照片信息
for (Element element : itemList) {
AlbumInfoDTO albumInfo = new AlbumInfoDTO();
//获取属性
albumInfo.setId(element.attributeValue("ID"));
//获取元素的文本 不管是不是CDATA都能获取文本信息
albumInfo.setName(element.getTextTrim());
albumList.add(albumInfo);
}
}
return albumList;
}
添加数据:
public void saveAlbum(String path, AlbumInfoDTO album) throws Exception {
if (StringUtils.isBlank(path) || null == album) {
return;
}
Document doc = XmlUtil.parse(path);
Element root = doc.getRootElement();
Element item = root.addElement("item");
//添加元素属性
item.addAttribute("id", album.getId());
//添加元素CDATA文本内容
item.addCDATA("xxxx");
//在元素下再添加名称为content包含CDATA节点的的元素
item.element("content").addCDATA("content");
//再元素下设置普通文本内容
item.setText(album.getFloderName());
XmlUtil.write(doc, path);
}