增强Dom4j--让XML处理更容易
 
Java处理XML的工具包中,Dom4j是佼佼者,但是使用起来还是不够简洁。
为更方便使用Dom4j处理XML,这里做了一些工具类库,放出来以供参考。
 
一、文件与字符串相互转换的工具
处理XML文件读取的问题,实际上这个是一个文本文件读取的问题。
 
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.*;

/**
* 字符串与文件相互转换工具
*
* @author leizhimin 2009-11-11 15:54:18
*/

public class StringFileToolkit {
        private static Log log = LogFactory.getLog(StringFileToolkit.class);

        /**
         * 读取输入流为一个内存字符串,保持文件原有的换行格式
         *
         * @param in            输入流
         * @param charset 文件字符集编码
         * @return 文件内容的字符串
         */

        public static String file2String(InputStream in, String charset) {
                StringBuffer sb = new StringBuffer();
                try {
                        LineNumberReader reader = new LineNumberReader(new BufferedReader(new InputStreamReader(in, charset)));
                        String line;
                        while ((line = reader.readLine()) != null) {
                                sb.append(line).append(System.getProperty("line.separator"));
                        }
                        reader.close();
                } catch (UnsupportedEncodingException e) {
                        log.error("读取文件为一个内存字符串失败,失败原因是使用了不支持的字符编码" + charset, e);
                } catch (IOException e) {
                        log.error("读取文件为一个内存字符串失败,失败原因是读取文件异常!", e);
                }
                return sb.toString();
        }

        /**
         * 读取文件为一个内存字符串,保持文件原有的换行格式
         *
         * @param file        文件对象
         * @param charset 文件字符集编码
         * @return 文件内容的字符串
         */

        public static String file2String(File file, String charset) {
                StringBuffer sb = new StringBuffer();
                try {
                        LineNumberReader reader = new LineNumberReader(new BufferedReader(new InputStreamReader(new FileInputStream(file), charset)));
                        String line;
                        while ((line = reader.readLine()) != null) {
                                sb.append(line).append(System.getProperty("line.separator"));
                        }
                        reader.close();
                } catch (UnsupportedEncodingException e) {
                        log.error("读取文件为一个内存字符串失败,失败原因是使用了不支持的字符编码" + charset, e);
                } catch (FileNotFoundException e) {
                        log.error("读取文件为一个内存字符串失败,失败原因所给的文件" + file + "不存在!", e);
                } catch (IOException e) {
                        log.error("读取文件为一个内存字符串失败,失败原因是读取文件异常!", e);
                }
                return sb.toString();
        }

        /**
         * 将字符串存储为一个文件,当文件不存在时候,自动创建该文件,当文件已存在时候,重写文件的内容,特定情况下,还与操作系统的权限有关。
         *
         * @param text         字符串
         * @param distFile 存储的目标文件
         * @return 当存储正确无误时返回true,否则返回false
         */

        public static boolean string2File(String text, File distFile) {
                if (!distFile.getParentFile().exists()) distFile.getParentFile().mkdirs();
                BufferedReader br = null;
                BufferedWriter bw = null;
                boolean flag = true;
                try {
                        br = new BufferedReader(new StringReader(text));
                        bw = new BufferedWriter(new FileWriter(distFile));
                        char buf[] = new char[1024 * 64];         //字符缓冲区
                        int len;
                        while ((len = br.read(buf)) != -1) {
                                bw.write(buf, 0, len);
                        }
                        bw.flush();
                        br.close();
                        bw.close();
                } catch (IOException e) {
                        flag = false;
                        log.error("将字符串写入文件发生异常!", e);
                }
                return flag;
        }

        public static void main(String[] args) {
                String x = file2String(new File("C:\\a.txt"), "GBK");
                System.out.println(x);

                boolean b = string2File(x, new File("C:\\b.txt"));
                System.out.println(b);
        }
}
 
二、Doc文档的一些常用操作
 
构建Document文档对象,删除、添加XML元素,格式化XML。
 
package zzvcom.common;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.*;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.List;

/**
* XML便捷工具箱
*
* @author leizhimin 2009-11-11 16:26:19
*/

public class XmlToolkit {
        private static Log log = LogFactory.getLog(XmlToolkit.class);


        /**
         * 根据classpath下xml文件名创建一个XML文档对象,并制定读取字符集
         *
         * @param classPathFileName xml文件名称,
         * @param charset                     xml文件字符集编码
         * @return xml的字符串
         */

        public static Document makeDocument(String classPathFileName, String charset) {
                Document doc = null;
                try {
                        InputStream in = XmlToolkit.class.getClassLoader().getResourceAsStream(classPathFileName);
                        String xml = StringFileToolkit.stream2String(in, charset);
                        doc = DocumentHelper.parseText(xml);
                } catch (Exception e) {
                        log.error("解析XML发生错误,请检查ClassPath下面的" + classPathFileName + "文件是否存在,格式是否是正确!");
                        throw new RuntimeException(e);
                }
                return doc;
        }

        /**
         * 创建一个XML文档对象
         *
         * @param xmlfile xml文件
         * @param charset xml文件字符集编码
         * @return xml的字符串
         */

        public static Document makeDocument(File xmlfile, String charset) {
                Document doc = null;
                try {
                        String xml = StringFileToolkit.file2String(xmlfile, charset);
                        doc = DocumentHelper.parseText(xml);
                } catch (Exception e) {
                        log.error("解析XML发生错误,请检查" + xmlfile.getPath() + "文件是否存在,格式是否是正确!");
                        throw new RuntimeException(e);
                }
                return doc;
        }

        /**
         * 删除文档doc的指定路径下的所有子节点(包含元素,属性等)
         *
         * @param doc     文档对象
         * @param xpath 指定元素的路径
         * @return 删除成功时返回true,否则false
         */

        public static boolean deleteNodes(Document doc, String xpath) {
                boolean flag = true;
                try {
                        List<Node> nlist = doc.selectNodes(xpath);
                        for (Node node : nlist) {
                                node.detach();
                        }
                } catch (Exception e) {
                        flag = false;
                }
                return flag;
        }

        /**
         * 删除一个父元素下所有的子节点(包含元素,属性等)
         *
         * @param element 父元素
         * @return 删除成功时返回true,否则false
         */

        public static boolean deleteChildren(Element element) {
                boolean flag = true;
                try {
                        List<Node> nlist = element.elements();
                        for (Node node : nlist) {
                                node.detach();
                        }
                } catch (Exception e) {
                        flag = false;
                }
                return flag;
        }

        /**
         * 在指定文档doc的xpath元素下面添加ename子元素,并给出子元素的text值
         *
         * @param doc        文档对象
         * @param xpath    父元素的xpath
         * @param ename    所加入子元素名称
         * @param evalue 所加入子元素的text值
         * @return 加入后的xml元素
         */

        public static Element addElement(Document doc, String xpath, String ename, String evalue) {
                Element element = null;
                Node n = (Node) doc.selectSingleNode(xpath);
                if (n instanceof Element) {
                        Element e = (Element) n;
                        element = e.addElement(ename);
                        element.setText(evalue);
                }
                return element;
        }

        /**
         * 在指定文档doc的xpath元素下面添加xml文档为子元素
         *
         * @param doc     文档对象
         * @param xpath 父元素的xpath
         * @param xml     要加入的xml文档
         * @return 所加入后的xml元素
         */

        public static Element addElementByString(Document doc, String xpath, String xml) {
                Element subdoc = null;
                try {
                        subdoc = DocumentHelper.parseText(xml).getRootElement();
                } catch (DocumentException e) {
                        e.printStackTrace();
                }
                Node n = (Node) doc.selectSingleNode(xpath);
                if (n instanceof Element) {
                        Element e = (Element) n;
                        e.add(subdoc);
                        System.out.println(subdoc.getPath());
                }
                return subdoc;
        }

        /**
         * 格式化XML文档
         *
         * @param document xml文档
         * @param charset    字符串的编码
         * @return 格式化后XML字符串
         */

        public static String formatXML(Document document, String charset) {
                OutputFormat format = OutputFormat.createPrettyPrint();
                format.setEncoding(charset);
                StringWriter sw = new StringWriter();
                XMLWriter xw = new XMLWriter(sw, format);
                try {
                        xw.write(document);
                        xw.flush();
                        xw.close();
                } catch (IOException e) {
                        log.error("格式化XML文档发生异常,请检查!", e);
                }
                return sw.toString();
        }
}
 
 
测试输出结果:
/platscheme/scheme/vcom
<?xml version="1.0" encoding="GBK"?>
<platscheme>
        <schemeName/>
        <schemeId/>
        <platformname>1</platformname>
        <platformId>1</platformId>
        <updCapacity>1</updCapacity>
        <onlineCapacity>1</onlineCapacity>
        <delCapacity>1</delCapacity>
        <scheme><movies><del><movie mpeg="" moviename="" generid="0" onlinedate=""/>
                        </del></movies>
        <vcom>
  <ftpinfo>
    <serverip>127.0.0.1</serverip>
    <serverport>21</serverport>
    <username>ftpnv2cds1</username>
    <password>ftp</password>
  </ftpinfo>

  <webserviceinfo>
    <serverip>127.0.0.1</serverip>
    <serverport>8888</serverport>
  </webserviceinfo>

  <planinfo>
    <!--璁″垝缂栧彿-->
    <planid>filename</planid>
    <downloadfile>
      <!--闇�瑕佷笅杞界殑鏂囦欢淇℃伅-->
      <plandata plandataid="1" filepath="/" filename="filename"/>
    </downloadfile>
  </planinfo>
</vcom></scheme>
</platscheme>
-----------------------------
<?xml version="1.0" encoding="UTF-8"?>

<platscheme>    
    <schemeName/>    
    <schemeId/>    
    <platformname>1</platformname>    
    <platformId>1</platformId>    
    <updCapacity>1</updCapacity>    
    <onlineCapacity>1</onlineCapacity>    
    <delCapacity>1</delCapacity>    
    <scheme>
        <movies>
            <del>
                <movie mpeg="" moviename="" generid="0" onlinedate=""/>    
            </del>
        </movies>    
        <vcom>    
            <ftpinfo>    
                <serverip>127.0.0.1</serverip>    
                <serverport>21</serverport>    
                <username>ftpnv2cds1</username>    
                <password>ftp</password>    
            </ftpinfo>    
            <webserviceinfo>    
                <serverip>127.0.0.1</serverip>    
                <serverport>8888</serverport>    
            </webserviceinfo>    
            <planinfo>    
                <!--璁″垝缂栧彿-->    
                <planid>filename</planid>    
                <downloadfile>    
                    <!--闇�瑕佷笅杞界殑鏂囦欢淇℃伅-->    
                    <plandata plandataid="1" filepath="/" filename="filename"/>    
                </downloadfile>    
            </planinfo>    
        </vcom>
    </scheme>    
</platscheme>


Process finished with exit code 0
 
有了以上的扩展,结合Dom4j,处理XML的工作会变得相当轻松容易。