DOM4j 是一致评价很高的一款开源XML解析器 支持XPath XML XSLT DOM SAX 和 JAXP 并自带了一个SAX解析器
可以说是一个 20% - 80% 的工具(这个好像是JDOM的声明)
先看看API
org.dom4j.DocumentHelper
这个类的所有的方法都是static的 可以简单的用来创建document element attribute 等等
org.dom4j.DocumentFactory
这个类是工厂方法的集合用来简单构建DOM4J树
OutputFormat
这个类用来设置格式和字符编码等等
XMLWriter
标准的输出类
Document和Element都是实现了Brance这个接口
现在利用DOM4J来简单的输出一个xml文档
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
public class TestWriteXML
... {
public static void main(String[] args)throws IOException, DocumentException
...{
DocumentFactory dFactory=DocumentFactory.getInstance();
Document doc=dFactory.createDocument();
Element element=dFactory.createElement("ergal");
doc.setRootElement(element);
element.addAttribute("id", "007");
Element eName=element.addElement("name");
Element eAge=element.addElement("age");
eName.setText("wang");
eAge.setText("24");
FileOutputStream fos=new FileOutputStream("test.xml");
OutputFormat of=new OutputFormat(" ", true);
XMLWriter xw=new XMLWriter(fos, of);
xw.write(doc);
xw.close();
}
}
中间用OutputFormat来设置了格式
还有如果是用java.io.Write构造的输出不会自动刷新 需要在write之后手动刷新
输出:
< ergal id ="007" >
< name > wang </ name >
< age > 24 </ age >
</ ergal >
我这用的是DocumentFactory 也可以用DocumentHelper的static方法来实现 Element也可以
import java.io.FileOutputStream;
import java.io.IOException;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.DocumentException;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
public class TestWriteXML
... {
public static void main(String[] args)throws IOException, DocumentException
...{
//DocumentFactory dFactory=DocumentFactory.getInstance();
//Document doc=dFactory.createDocument();
Document doc=DocumentHelper.createDocument();
Element element=DocumentHelper.createElement("ergal");
doc.setRootElement(element);
element.addAttribute("id", "007");
Element eName=element.addElement("name");
Element eAge=element.addElement("age");
eName.setText("wang");
eAge.setText("24");
FileOutputStream fos=new FileOutputStream("test.xml");
OutputFormat of=new OutputFormat(" ", true);
XMLWriter xw=new XMLWriter(fos, of);
xw.write(doc);
xw.close();
}
}
结果是一样的
SAX
现在来看DOM4J的SAX的实现
解析XML的方法有很多 SAX是性能较好的一种 在DOM4J中用SAXReader来获得DOM4J树
在DOM4J中 和JAXP一样 Node是核心 其他的接口(如Attribut Document等等)都是对Node的扩展
在JAXP中的Node没有accept方法 在DOM4J中Node多了一种方法accept
void | accept(Visitor visitor) accept is the method used in the Visitor Pattern. |
此方法允许你传进一个实现了Visitor的类 这个类一看API就知道了
void | visit(Attribute node) Visits the given Attribute |
void | visit(CDATA node) Visits the given CDATA |
void | visit(Comment node) Visits the given Comment |
void | visit(Document document) Visits the given Document |
void | visit(DocumentType documentType) Visits the given DocumentType |
void | visit(Element node) Visits the given Element |
void | visit(Entity node) Visits the given Entity |
void | visit(Namespace namespace) Visits the given Namespace |
void | visit(ProcessingInstruction node) Visits the given ProcessingInstruction |
void | visit(Text node) Visits the given Text |
可以定制回调时所用的类 这个实现了Visitor的类的方法 可以自己添加处理方式来根据自己的需要解析XML
实例:解析一个XML
hibernate.cfg.xml
<! DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd" >
<!-- Generated by MyEclipse Hibernate Tools. -->
< hibernate-configuration >
< session-factory >
< property name ="connection.driver_class" > com.mysql.jdbc.Driver </ property >
< property name ="connection.url" > jdbc:mysql://localhost:3306/sshtest </ property >
< property name ="connection.username" > root </ property >
< property name ="connection.password" > 00000000 </ property >
<!-- JDBC connection pool -->
< property name ="hibernate.connection.provider_class" > org.hibernate.connection.C3P0ConnectionProvider </ property >
< property name ="hibernate.c3p0.max_size" > 20 </ property >
< property name ="hibernate.c3p0.min_size" > 5 </ property >
< property name ="hibernate.c3p0.timeout" > 120 </ property >
< property name ="hibernate.c3p0.max_statements" > 100 </ property >
< property name ="hibernate.c3p0.idle_test_period" > 120 </ property >
< property name ="hibernate.c3p0.acquire_increment" > 2 </ property >
< property name ="hibernate.transaction.factory_class" > org.hibernate.transaction.JDBCTransactionFactory </ property >
<!-- SQL dialect -->
< property name ="dialect" > org.hibernate.dialect.MySQLDialect </ property >
< property name ="current_session_context_class" > thread </ property >
< property name ="cache.provider_class" > org.hibernate.cache.NoCacheProvider </ property >
< property name ="show_sql" > true </ property >
<!-- <property name="hbm2ddl.auto">create</property> -->
< mapping resource ="com/ergal/hibernate/pojo/User.hbm.xml" />
< mapping resource ="com/ergal/hibernate/pojo/Artist.hbm.xml" />
< mapping resource ="com/ergal/hibernate/pojo/Category.hbm.xml" />
< mapping resource ="com/ergal/hibernate/pojo/FileType.hbm.xml" />
< mapping resource ="com/ergal/hibernate/pojo/MyFile.hbm.xml" />
< mapping resource ="com/ergal/hibernate/pojo/MyLocation.hbm.xml" />
< mapping resource ="com/ergal/hibernate/pojo/MyPackage.hbm.xml" />
< mapping resource ="com/ergal/hibernate/pojo/MyPic.hbm.xml" />
</ session-factory >
</ hibernate-configuration >
先写一个类来扩展VisitorSupport
SAXParserTest.java
import org.dom4j.Attribute;
import org.dom4j.Element;
import org.dom4j.VisitorSupport;
public class SAXParserTest extends VisitorSupport
... {
//打印属性的名字和值
public void visit(Attribute node)
...{
System.out.println("attribute: "+node.getName()+" value: "+ node.getValue());
}
public void visit(Element node)
...{
//如果只有文本就打印 元素名和文本
if(node.isTextOnly())
...{
System.out.println("element:" +node.getName()+" text: "+node.getTextTrim());
}
//否则只打印 元素名
else
...{
System.out.println("element:" +node.getName());
}
}
}
然后写一个解析的类
ParserTest.java
import java.io.File;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
public class ParserTest
... {
public static void main(String[] args)
...{
SAXReader sr=new SAXReader();
File f=new File("bin/hibernate.cfg.xml");
try
...{
Document doc=sr.read(f);
doc.accept(new SAXParserTest());
}catch(DocumentException e)
...{
System.out.println(e.getMessage());
}
}
}
最后的输出如下:
element:session-factory
element:property text: com.mysql.jdbc.Driver
attribute: name value: connection.driver_class
element:property text: jdbc:mysql://localhost:3306/sshtest
attribute: name value: connection.url
element:property text: root
attribute: name value: connection.username
element:property text: 00000000
attribute: name value: connection.password
element:property text: org.hibernate.connection.C3P0ConnectionProvider
attribute: name value: hibernate.connection.provider_class
element:property text: 20
attribute: name value: hibernate.c3p0.max_size
element:property text: 5
attribute: name value: hibernate.c3p0.min_size
element:property text: 120
attribute: name value: hibernate.c3p0.timeout
element:property text: 100
attribute: name value: hibernate.c3p0.max_statements
element:property text: 120
attribute: name value: hibernate.c3p0.idle_test_period
element:property text: 2
attribute: name value: hibernate.c3p0.acquire_increment
element:property text: org.hibernate.transaction.JDBCTransactionFactory
attribute: name value: hibernate.transaction.factory_class
element:property text: org.hibernate.dialect.MySQLDialect
attribute: name value: dialect
element:property text: thread
attribute: name value: current_session_context_class
element:property text: org.hibernate.cache.NoCacheProvider
attribute: name value: cache.provider_class
element:property text: true
attribute: name value: show_sql
element:mapping text:
attribute: resource value: com/ergal/hibernate/pojo/User.hbm.xml
element:mapping text:
attribute: resource value: com/ergal/hibernate/pojo/Artist.hbm.xml
element:mapping text:
attribute: resource value: com/ergal/hibernate/pojo/Category.hbm.xml
element:mapping text:
attribute: resource value: com/ergal/hibernate/pojo/FileType.hbm.xml
element:mapping text:
attribute: resource value: com/ergal/hibernate/pojo/MyFile.hbm.xml
element:mapping text:
attribute: resource value: com/ergal/hibernate/pojo/MyLocation.hbm.xml
element:mapping text:
attribute: resource value: com/ergal/hibernate/pojo/MyPackage.hbm.xml
element:mapping text:
attribute: resource value: com/ergal/hibernate/pojo/MyPic.hbm.xml
可以看到完全是和过程相关的 有什么节点就怎么解析 碰到元素就调用元素的事件 碰到属性就调用属性的事件