一,dom4j简介
dom4j是一个Java的XML API,是jdom的升级品,用来读写XML文件的。dom4j是一个十分优秀的JavaXML API,具有性能优异、功能强大和极其易使用的特点,它的性能超过sun公司官方的dom技术,同时它也是一个开放源代码的软件,可以在SourceForge上找到它。在IBM developerWorks上面还可以找到一篇文章,对主流的Java XML API进行的性能、功能和易用性的评测,所以可以知道dom4j无论在哪个方面都是非常出色的。如今可以看到越来越多的Java软件都在使用dom4j来读写XML,特别值得一提的是连Sun的JAXM也在用dom4j。这已经是必须使用的jar包, Hibernate也用它来读写配置文件。
DOM4J是 dom4j.org 出品的一个开源 XML 解析包。DOM4J应用于 Java 平台,采用了 Java 集合框架并完全支持 DOM,SAX 和 JAXP。
DOM4J 使用起来非常简单。只要你了解基本的 XML-DOM 模型,就能使用。
DOM4J使用需要下载两个jar包,缺一不可,不然会报错。jar包下载链接
dom4j-1.6.1.jar
jaxen-1.1.6.jar
dom4j的使用程序实例
程序实例1
第一个程序,用Java代码生成xml文档,代码如下:
package com.xml;
import java.io.FileOutputStream;
import java.io.FileWriter;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
/**
* dom4j框架学习 使用dom4j框架创建xml文档并输出保存
*
*/
public class Dom4JTest1
{
public static void main(String[] args) throws Exception
{
// 第一种方式:创建文档,并创建根元素
// 创建文档:使用了一个Helper类
Document document = DocumentHelper.createDocument();
// 创建根节点并添加进文档
Element root = DocumentHelper.createElement("student");
document.setRootElement(root);
// 第二种方式:创建文档并设置文档的根元素节点
Element root2 = DocumentHelper.createElement("student");
Document document2 = DocumentHelper.createDocument(root2);
// 添加属性
root2.addAttribute("name", "zhangsan");
// 添加子节点:add之后就返回这个元素
Element helloElement = root2.addElement("hello");
Element worldElement = root2.addElement("world");
helloElement.setText("hello Text");
worldElement.setText("world text");
// 输出
// 输出到控制台
XMLWriter xmlWriter = new XMLWriter();
xmlWriter.write(document);
// 输出到文件
// 格式
OutputFormat format = new OutputFormat(" ", true);// 设置缩进为4个空格,并且另起一行为true
XMLWriter xmlWriter2 = new XMLWriter(
new FileOutputStream("student.xml"), format);
xmlWriter2.write(document2);
// 另一种输出方式,记得要调用flush()方法,否则输出的文件中显示空白
XMLWriter xmlWriter3 = new XMLWriter(new FileWriter("student2.xml"),
format);
xmlWriter3.write(document2);
xmlWriter3.flush();
// close()方法也可以
}
}
运行结果:
程序实例2
程序实例2,读入xml文档并分析,将其内容输出。
首先,待分析的文档如下:
<?xml version="1.0" encoding="UTF-8"?>
<students name="zhangsan">
<hello name="lisi">hello Text1</hello>
<hello name="lisi2">hello Text2</hello>
<hello name="lisi3">hello Text3</hello>
<world name="wangwu">world text1</world>
<world name="wangwu2">world text2</world>
<world >world text3</world>
</students>
Java代码:
package com.xml;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.DOMReader;
import org.dom4j.io.SAXReader;
/**
* dom4j框架学习: 读取并解析xml
*
*
*/
public class Dom4JTest2
{
public static void main(String[] args) throws Exception
{
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File("students.xml"));
// 获取根元素
Element root = document.getRootElement();
System.out.println("Root: " + root.getName());
// 获取所有子元素
List<Element> childList = root.elements();
System.out.println("total child count: " + childList.size());
// 获取特定名称的子元素
List<Element> childList2 = root.elements("hello");
System.out.println("hello child: " + childList2.size());
// 获取名字为指定名称的第一个子元素
Element firstWorldElement = root.element("world");
// 输出其属性
System.out.println("first World Attr: "
+ firstWorldElement.attribute(0).getName() + "="
+ firstWorldElement.attributeValue("name"));
System.out.println("迭代输出-----------------------");
// 迭代输出
for (Iterator iter = root.elementIterator(); iter.hasNext();)
{
Element e = (Element) iter.next();
System.out.println(e.attributeValue("name"));
}
System.out.println("用DOMReader-----------------------");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
// 注意要用完整类名
org.w3c.dom.Document document2 = db.parse(new File("students.xml "));
DOMReader domReader = new DOMReader();
// 将JAXP的Document转换为dom4j的Document
Document document3 = domReader.read(document2);
Element rootElement = document3.getRootElement();
System.out.println("Root: " + rootElement.getName());
}
}
DOM4J
Dom:把整个文档作为一个对象。 DOM4J 最大的特色是使用大量的接口。它的主要接口都在org.dom4j里面定义:
类 | 作用 |
---|---|
Document | 表示整个XML文档。文档Document对象是通常被称为DOM树。 |
Element | 表示一个XML元素。 Element对象有方法来操作其子元素,它的文本,属性和名称空间。 |
Attribute | 表示元素的属性。属性有方法来获取和设置属性的值。它有父节点和属性类型。 |
Node | 代表元素,属性或处理指令。 |
Entity | 定义 XML entity |
DOM4J工具类
在项目中会经常遇到操作xml的情景,不可能每次都去写对xml的操作,这样代码会显得很笨重,重复利用率不高,所以在这里给大家一个xml的工具类。
package com.xml;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
/**
*
* 描述 DOM4j XML 工具类
* @author fts
* @created 2017年8月16日
*/
public final class XmlUtil {
/**
* 使用的查询子孙节点的路径
*/
private static final String SELECT_PATH = ".//";
/**
* 默认编码
*/
private static final String DEFAULT_ENCODING = "UTF-8";
// Constructors
/** default constructor */
private XmlUtil() {
}
/**
*
* 描述 取得当前节点特定子节点的正文,只取第一个
* @author fts
* @created 2017年8月16日
* @param element 当前XML节点
* @param fieldCode 正文内容
* @return
*/
public static String getSonFieldContent(final Element element, final String fieldCode) {
if (element == null) {
return null;
}
String content = null;
Element ele = element.element(fieldCode);
if (ele != null) {
content = ele.getText();
}
return content;
}
/**
*
* 描述 取得当前节点特定子孙节点的正文,只取第一个
* @author fts
* @created 2017年8月16日
* @param element 操作的xml元素
* @param fieldCode 栏位名称
* @return
*/
public static Element getDesFieldElement(final Element element, final String fieldCode) {
Element tagertElement = null;
@SuppressWarnings("unchecked")
List<Element> list = element.selectNodes(SELECT_PATH + fieldCode);
if (list.size() > 0) {
tagertElement = list.get(0);
}
return tagertElement;
}
/**
*
* 描述 取得当前节点特定子孙节点的正文,只取第一个
* @author fts
* @created 2017年8月16日
* @param text 传入报文
* @param fieldCode 标签代码
* @return 标签内容
* @throws DocumentException
*/
public static String getDesFieldText(final String text, final String fieldCode) throws DocumentException {
Element rootEle = DocumentHelper.parseText(text).getRootElement();
Element desFieldEle = getDesFieldElement(rootEle, fieldCode);
if (desFieldEle != null) {
return desFieldEle.getText();
} else {
return null;
}
}
/**
*
* 描述 取得当前节点特定子孙节点的正文,制定个数
* @author fts
* @created 2017年8月16日
* @param text 传入报文
* @param fieldCode 标签代码
* @param index 处理的元素索引
* @return 标签内容
* @throws DocumentException
*/
public static String getDesFieldTextByIndex(final String text, final String fieldCode, final int index)
throws DocumentException {
Element rootEle = DocumentHelper.parseText(text).getRootElement();
List<Element> eleList = (List<Element>) rootEle.selectNodes(SELECT_PATH + fieldCode);
if (eleList.size() > index) {
return eleList.get(index).getText();
} else {
return null;
}
}
/**
*
* 描述 取得子孙节点集合
* @author fts
* @created 2017年8月16日
* @param element 操作的xml元素
* @param fieldCode 栏位名称
* @return 正文内容
*/
@SuppressWarnings("unchecked")
public static List<Element> getDesFieldElementList(final Element element, final String fieldCode) {
return element.selectNodes(SELECT_PATH + fieldCode);
}
/**
*
* 描述 取得当前节点下所有拥有当前属性的元素
* @author fts
* @created 2017年8月16日
* @param element 当前元素
* @param fieldCode 查找属性名称
* @return
*/
public static List<Element> getEleListByAttr(final Element element, final String fieldCode) {
// 返回数据
List<Element> eleList = new ArrayList<Element>();
// 查找并循环添加
@SuppressWarnings("unchecked")
List<Attribute> attrList = element.selectNodes(SELECT_PATH + "@" + fieldCode);
for (Attribute attr : attrList) {
eleList.add(attr.getParent());
}
// 返回
return eleList;
}
/**
*
* 描述 取得当前节点下所有拥有当前属性的元素
* @author fts
* @created 2017年8月16日
* @param msgText 当前元素
* @param path 查找属性名称
* @return
*/
public static List<Element> getEleListByPath(final String msgText, final String path) {
// 返回数据
List<Element> eleList = new ArrayList<Element>();
try {
Document document;
document = DocumentHelper.parseText(msgText);
eleList = document.selectNodes(path);
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 返回
return eleList;
}
/**
*
* 描述 一次性增加多个子节点
* @author fts
* @created 2017年8月16日
* @param fatherEle 父亲节点
* @param sonEleList 要增加的子节点元素
*/
public static void addElements(final Element fatherEle, final List<Element> sonEleList) {
for (Element ele : sonEleList) {
fatherEle.add((Element) ele.clone());
}
}
/**
*
* 描述 增加子元素
* @author fts
* @created 2017年8月16日
* @param fatherEle 父亲节点
* @param sonEleName 儿子节点名
* @param sonEleContent 儿子节点内容
* @return 儿子节点
*/
public static Element addElement(final Element fatherEle, final String sonEleName, final String sonEleContent) {
// 创建子节点
Element ele = DocumentHelper.createElement(sonEleName);
if (StringUtils.isNotBlank(sonEleContent)) {
ele.setText(sonEleContent);
}
// 关联
fatherEle.add(ele);
// 返回
return ele;
}
/**
*
* 描述 最后最后一级的子节点,如果传入数据为空不增加
* @author fts
* @created 2017年8月16日
* @param fatherEle 父亲节点
* @param sonEleName
* @param sonEleContent
* @return
*/
public static Element addFinalSonElement(final Element fatherEle, final String sonEleName,
final String sonEleContent) {
// 创建子节点
Element ele = null;
// 增加
if (StringUtils.isNotBlank(sonEleContent)) {
ele = DocumentHelper.createElement(sonEleName);
ele.setText(sonEleContent);
// 关联
fatherEle.add(ele);
}
// 返回
return ele;
}
/**
*
* 描述 取得XMl字符串中的指定路径字符
* @author fts
* @created 2017年8月16日
* @param text
* @param url
* @return
*/
public static String getUrlElementText(final String text, final String url) {
// 返回值
String resultText = null;
// 转化XML
Element busiElement;
try {
busiElement = DocumentHelper.parseText(text).getRootElement();
List<Element> eleList = busiElement.selectNodes(url);
if (eleList.size() > 0) {
resultText = ((Element) busiElement.selectNodes(url).get(0)).getText();
}
} catch (DocumentException e) {
e.printStackTrace();
}
// 返回
return resultText;
}
/**
*
* 描述
* @author fts
* @created 2017年8月16日
* @param doc
* @param url
* @return
*/
public static String getUrlElementText(Document doc, final String url) {
Node node = doc.selectSingleNode(url);
if (node == null) {
return null;
}
return node.getText();
}
/**
*
* 描述 格式化xml字符串
* @author fts
* @created 2017年8月16日
* @param xmlText xml字符串
* @return 格式化后的字符
* @throws Exception
*/
public static String formatXml(final String xmlText) throws Exception {
// 返回字符串
String reText;
try {
reText = formatXml(xmlText, DEFAULT_ENCODING);
} catch (Exception e) {
throw new Exception(e.getMessage());
}
// 返回
return reText;
}
/**
*
* 描述 格式化xml字符串
* @author fts
* @created 2017年8月16日上午11:26:19
* @param xmlText xml字符串
* @param inEncoding 字符编码
* @return 格式化后的字符
* @throws Exception
*/
public static String formatXml(final String xmlText, final String inEncoding) throws Exception {
String encoding = inEncoding;
// 返回字符串
String reText;
if (StringUtils.isBlank(encoding)) {
encoding = DEFAULT_ENCODING;
}
// 转化
try {
// 将字符串格式转换成document对象
Document document = DocumentHelper.parseText(xmlText);
// 注意,用这种方式来创建指定格式的format
OutputFormat format = OutputFormat.createPrettyPrint();
format.setEncoding(encoding);
// 创建String输出流
StringWriter out = new StringWriter();
// 包装String流
XMLWriter writer = new XMLWriter(out, format);
// 将当前的document对象写入底层流out中
writer.write(document);
writer.close();
reText = out.toString();
} catch (Exception e) {
String errTagMsg = "数据格式化失败!";
throw new Exception(errTagMsg);
}
// 返回
return reText;
}
/**
*
* 描述 复制XML元素的值到对应的对象属性当中
* @author fts
* @created 2017年8月16日
* @param obj 配置对象
* @param ele XML元素
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws ClassNotFoundException
*/
@SuppressWarnings("unchecked")
public static void copyEleToAttr(final Object obj, final Element ele)
throws IllegalArgumentException, IllegalAccessException, InstantiationException, ClassNotFoundException {
// 获取f对象对应类中的所有属性域
Field[] fields = obj.getClass().getDeclaredFields();
for (int i = 0, len = fields.length; i < len; i++) {
// 对于每个属性,获取属性名
String fieldName = fields[i].getName();
fields[i].setAccessible(true);
/**
* String属性直接进行赋值,如果是复杂类,进行下一步赋值
*/
if (fields[i].getType().equals(String.class)) {
String eleContent = XmlUtil.getSonFieldContent(ele, fieldName);
if (eleContent != null && !eleContent.equals("")) {
fields[i].set(obj, eleContent);
}
} else if (fields[i].getType().equals(List.class)) {
String eleName = fieldName.substring(0, fieldName.length() - 4);
List<Element> eleList = ele.elements(eleName);
List<Object> field = (List<Object>) fields[i].get(obj);
// 取得泛型类型
Type fc = fields[i].getGenericType();
ParameterizedType pt = (ParameterizedType) fc;
Class driveClass = (Class) pt.getActualTypeArguments()[0];
try {
for (Element singleEle : eleList) {
Object singObjct = driveClass.newInstance();
// 判断是否是字符串
if (driveClass.equals(String.class)) {
singObjct = singleEle.getText();
} else {
copyEleToAttr(singObjct, singleEle);
}
field.add(singObjct);
}
} catch (Exception e) {
for (Element singleEle : eleList) {
String eleContent = singleEle.getTextTrim();
if (eleContent != null && !eleContent.equals("")) {
field.add(eleContent);
}
}
}
} else {
Object fieldObject = fields[i].get(obj);
Element fieldEle = ele.element(fieldName);
if (fieldObject != null && fieldEle != null) {
copyEleToAttr(fieldObject, fieldEle);
}
}
}
}
/**
*
* 描述 复制对应的对象属性当到XML元素的值中
* @author fts
* @created 2017年8月16日
* @param obj 配置对象
* @param ele XML元素
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
@SuppressWarnings("unchecked")
public static void copyAttrToEle(final Object obj, final Element ele)
throws IllegalArgumentException, IllegalAccessException {
// 获取f对象对应类中的所有属性域
Field[] fields = obj.getClass().getDeclaredFields();
for (int i = 0, len = fields.length; i < len; i++) {
// 对于每个属性,获取属性名
String fieldName = fields[i].getName();
fields[i].setAccessible(true);
// 过滤不处理的对象
if (Modifier.isStatic(fields[i].getModifiers())) {
continue;
}
/**
* String属性直接进行赋值,如果是复杂类,进行下一步赋值
*/
if (fields[i].getType().equals(String.class)) {
XmlUtil.addFinalSonElement(ele, fieldName, (String) fields[i].get(obj));
} else if (fields[i].getType().equals(List.class)) {
List<Object> fieldList = (List<Object>) fields[i].get(obj);
for (Object object : fieldList) {
if (object.getClass().equals(String.class)) {
XmlUtil.addElement(ele, fieldName, (String) object);
} else {
copyAttrToEle(object, XmlUtil.addElement(ele, fieldName, null));
}
}
} else {
Object fieldObject = fields[i].get(obj);
if (fieldObject != null) {
Element fieldEle = XmlUtil.addElement(ele, fieldName, null);
copyAttrToEle(fields[i].get(obj), fieldEle);
}
}
}
}
}