1 前言
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也用它来读写配置文件。
1.1 官网
https://dom4j.github.io/
1.2 Document是什么
一个位于org.dom4j包下的接口
可以把它理解成一个xml树
2 XML和字符串互转
2.1 xml样式
<?xml version="1.0" encoding="UTF-8"?>
<ROOT>
<Header>
<ServiceName>报文头</ServiceName>
</Header>
<Body>
<ELEMENT>有值无属性的标签</ELEMENT>
</Body>
<USER name="James" sex="男" location="CN">人员</USER>
<DATABASE host="localhost" port="3306" username="root" password="root"/>
</ROOT>
2.2 导入jar包
<dependency>
<groupId>org.dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.1</version>
</dependency>
2.2 生成Document树并且转换为字符串
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
public class XMLUtils {
private static final String MSG_ENCODING="UTF-8";
/**
* @time 2021/08/21 11:35
* @author wdc
* @return xml报文字符串
*
*/
public static String genXmlDemo(){
// 创建报文
Document document = DocumentHelper.createDocument();
// 创建根节点
Element rootElement = document.addElement("ROOT");
// 创建报文头
Element headerElement = rootElement.addElement("Header");
headerElement.addElement("ServiceName").addText("报文头");
// 创建报文体
Element bodyElement = rootElement.addElement("Body");
// 添加 有值无属性的标签
Element element1 = bodyElement.addElement("ELEMENT").addText("有值无属性的标签");
// 添加 有属性有值的标签
Element element2 = rootElement.addElement("USER")
.addAttribute("name", "James")
.addAttribute("sex", "男")
.addAttribute("location", "CN")
.addText("人员");
// 添加 有属性无值的标签
Element element3 = rootElement.addElement("DATABASE")
.addAttribute("host", "localhost")
.addAttribute("port", "3306")
.addAttribute("username", "root")
.addAttribute("password", "root");
// 设置报文格式
document.setXMLEncoding(MSG_ENCODING);
String string = document.asXML();
return string;
}
}
2.3 document树转字符串方法
public static String parseDocument(Document document) throws DocumentException {
String xml = document.asXML();
return xml;
}
2.4 将xml格式的字符串转换成Document树
public static Document parseText(String xml) throws DocumentException {
Document document = DocumentHelper.parseText(xml);
return document;
}
2.5 将 URL、File、InputStream转化成Document树
public static Document parseXMLFile(Object obj){
// 获取解析器对象
SAXReader reader = new SAXReader();
Document document = null;
try {
if(obj instanceof URL ){
document = reader.read((URL)obj);
}else if(obj instanceof File){
document = reader.read((File)obj);
}else if(obj instanceof InputStream){
document = reader.read((InputStream)obj);
}
} catch (DocumentException e) {
e.printStackTrace();
}
return document;
}
3 将xml通过反射解析成对象
private static <T> T parseToObj2(Element element, Class<T> clazz) throws IllegalAccessException, InstantiationException, ClassNotFoundException {
Object newInstance = clazz.newInstance();
//读取到所有属性
Field[] fields = clazz.getDeclaredFields();
//遍历每一个属性并且从节点中找到对应属性赋值
for (Field field : fields) {
String eleVal = element.element(field.getName()).getTextTrim();
field.setAccessible(true);
if (null != eleVal && eleVal.length()>0) {
if (field.getType() == Integer.class) {
field.set(newInstance, Integer.parseInt(eleVal));
}
if (field.getType() == String.class) {
field.set(newInstance, eleVal);
}
}
}
return (T) newInstance;
}
4 如何解析标签格式中含有冒号xml报文
4.1 创建含有命名空间的Document树
4.1.1 Document树样式
这里生成给所有的标签添加命名空间的document树
<?xml version="1.0" encoding="UTF-8"?>
<ROOT xmlns:person="http://com.xtc.vo.User">
<person:USER name="James1" sex="男" location="CN">人员1</person:USER>
<person:USER name="James2" sex="男" location="CN">人员2</person:USER>
<person:USER name="James3" sex="男" location="CN">人员3</person:USER>
</ROOT>
4.1.2 Java代码
public static Document genDocWithNamespace(){
// 创建报文
Document document = DocumentHelper.createDocument();
// 创建根节点
Element rootElement = document.addElement("ROOT");
rootElement.addNamespace("person","http://com.xtc.vo.User");
Element element1 = rootElement.addElement("person:USER")
.addAttribute("name", "James1")
.addAttribute("sex", "男")
.addAttribute("location", "CN")
.addText("人员1");
Element element2 = rootElement.addElement("person:USER")
.addAttribute("name", "James2")
.addAttribute("sex", "男")
.addAttribute("location", "CN")
.addText("人员2");
Element element3 = rootElement.addElement("person:USER")
.addAttribute("name", "James3")
.addAttribute("sex", "男")
.addAttribute("location", "CN")
.addText("人员3");
return document;
}
4.1.3 两种添加命名空间的方式
// 举个栗子,假如说根节点对象
// 方式1
Document document = DocumentHelper.createDocument();
// 创建名为ROOT的根节点
Element rootElement = document.addElement("ROOT");
rootElement.addNamespace("person","http://com.xtc.vo.User");
// 方式2
Document document = DocumentHelper.createDocument();
// 创建名为ROOT的根节点
Element rootElement = document.addElement("ROOT");
Namespace namespace = new Namespace("person","http://com.xtc.vo.User");
rootElement.add(namespace);
4.2 解析含有命名空间的Document树
这种解析这是一个demo,可以解析格式为 4.1.1样式的document树
public static void parseTextWithNameSpace(String xml) throws DocumentException {
Document document = DocumentHelper.parseText(xml);
Element rootElement = document.getRootElement();
rootElement.addNamespace("person","http://com.xtc.vo.User");
List<Element> elements = rootElement.elements("USER");
System.out.println(elements);
}