您的位置:首页 > 其它

[学习笔记]XML解析之DOM4J

2015-07-23 23:29 501 查看


DOM4J


XML解析


1.常用API

解析器:SAXReader
文档对象:Document
元素对象:Element
文档帮助类(用于创建节点):DocumentHelper
文档对象子类:DefaultElement
文档对象子类:BaseElement
格式化输出对象:OutputFormat
保存文件对象:XMLWriter


2.解析XML获取文档对象

publicstaticvoidmain(String[]args){//创建SAXReader对象SAXReaderreader=newSAXReader();//解析XML获取Document对象try{Documentdoc=reader.read("/bin/LocalList.xml");}catch(DocumentExceptione){e.printStackTrace();}}



3.获取节点文本内容

privatestaticStringgetElementText(Documentdoc){//获取根节点Elementroot=doc.getRootElement();//获取指定节点集合List<Element>elements=root.elements("City");//获取指定节点Elemente=elements.get(7);//获取指定节点的文本内容Stringtext=e.getText();returntext;}



4.递归获取所有节点的文本

privatestaticvoidgetAllElementText(Documentdoc){
//获取根节点
Elementroot=doc.getRootElement();
//递归遍历所有节点
recursion(root);
}
//使用深度优先搜索递归遍历所有节点
privatestaticvoidrecursion(Elementnode){
//如果非元素节点,则直接返回
if(node.getNodeType()!=Element.ELEMENT_NODE){
return;
}
//如果该节点无子元素节点,则输出元素文本
if(node.elements().isEmpty()){
System.out.println(node.getText());
}else{
//如果该节点有子元素,则递归遍历
List<Element>elements=node.elements();
for(Elementelement:elements){
//递归调用
recursion(element);
}
}
}



5.使用迭代器获取所有City节点的元素内容

privatestaticvoidgetCityElementText(Documentdoc){
//获取根元素节点
Elementroot=doc.getRootElement();
//使用元素迭代器进行迭代
for(Iterator<Element>iterator=root.elementIterator();iterator.hasNext();){
Elemente=iterator.next();
//如果该节点无子元素节点,则输出元素文本内容
if(e.elements().isEmpty()){
System.out.println(e.getText());
}
}
}



6.将Document保存到XML中

privatestaticvoidsaveXML(Documentdoc){
try{
//创建XML文件的字节输出流
OutputStreamout=newFileOutputStream("src/LocalList.xml");
//获取数据格式的对象,createCompactFormat紧凑格式,createPrettyPrint缩进格式
OutputFormatformat=OutputFormat.createPrettyPrint();
//创建XMLWriter对象
XMLWriterwriter=newXMLWriter(out,format);
//将DOM树写入XML文件
writer.write(doc);
//关闭资源
writer.close();
}catch(IOExceptione){
e.printStackTrace();
}
}



7.修改元素文本内容

privatestaticvoidupdate(Documentdoc){
//获取要修改节点
Elementroot=doc.getRootElement();
Elementelement=(Element)root.elements().get(3);
//修改文本内容
element.setText("天上人间");
//保存文件
saveXML(doc);
}



8.添加子元素节点

privatestaticvoidaddChild(Documentdoc){
//获取要添加的父元素节点
Elementroot=doc.getRootElement();
Elementcity=(Element)root.elements().get(3);
//创建要添加的子元素节点
Elementstreet=DocumentHelper.createElement("street");
//ElementstreetE1=newDefaultElement("street");
//ElementstreetE2=newBaseElement("street");
//设置节点的文本内容
street.setText("南天门大街");
//将子节点添加到父节点中
city.add(street);
//保存文件
saveXML(doc);
}



9.添加兄弟元素节点

publicstaticvoidaddSibling(Documentdoc){
//获取目标元素节点
Elementroot=doc.getRootElement();
List<Element>elist=root.elements("City");
//创建要添加的元素节点
Elementcity=newDefaultElement("City");//<City></City>
//设置新节点的文本
city.setText("哈哈区");
//在指定位置加入元素city
elist.add(4,city);
//保存文件
saveXML(doc);
}



10.删除指定节点

publicstaticvoidremoveElement(Documentdoc){
//获取要删除节点
Elementroot=doc.getRootElement();
Elementcity=(Element)root.elements("City").get(3);
Elementstreet=(Element)city.elements("street").get(0);
//用父节点删除子节点
city.remove(street);
//保存文件
saveXML(doc);
}



11.为节点添加属性

publicstaticvoidaddAttribute(Documentdoc){
//获取要添加属性的节点
Elementroot=doc.getRootElement();
Elementcity=(Element)root.elements("City").get(3);
//为节点添加属性
city.addAttribute("type","food");
//保存文件
saveXML(doc);
}



XPath


概述

XPath的作用就像在一个文件系统中定位文件一样在XML文件中定位元素,XPath是由W3C的XPath1.0标准所描述。


标准


1.如果路径以斜线/开始,那么该路径就表示到一个元素的绝对路径。

/AAA/CCC:选择AAA的所有CCC子元素。


2.如果路径以双斜线//开头,则表示选择文档中所有满足双斜线//之后规则的元素(无论层级关系)。

//DDD/BBB:选择父元素是DDD的所有BBB元素。


3.星号*表示选择所有由星号之前的路径所定位的元素。

/*/*/*/BBB:选择所有的有3个祖先元素的BBB元素。

//*:选择所有元素。


4.方块号里的表达式可以进一步的指定元素,其中数字表示元素在选择集里的位置,而last()函数则表示选择集中的最后一个元素。

/AAA/BBB[1]:选择AAA的第一个BBB子元素。

/AAA/BBB[last()]:选择AAA的最后一个BBB子元素。


5.使用@符号来选择特定的属性或特定属性的元素。

//@id:选择所有的id属性。

//BBB[@id]:选择有id属性的BBB元素。

//BBB[not(@*)]:选择没有属性的BBB元素。


6.属性的值可以被用来作为选择的准则,normalize-space函数删除了前部和尾部的空格,并且把连续的空格串替换为一个单一的空格。

//BBB[@id='b1']:选择含有属性id且其值为'b1'的BBB元素。

//BBB[normalize-space(@name)='bbb']:选择含有属性name且其值(在用normalize-space函数去掉前后空格后)为'bbb'的BBB元素。


7.多个路径可以用分隔符|合并在一起。

/AAA/EEE|//BBB:选择所有的BBB元素和作为AAA子元素的所有EEE元素。


8.相关函数

count():计数所选元素的个数。

name():返回元素的名称。

start-with():在该函数的第一个参数字符串是以第二个参数字符开始的情况返回true。

contains():当其第一个字符串参数包含有第二个字符串参数时返回true。

string-length:返回字符串的字符数,应用<替代<,用>代替>。

//*[count(BBB)=2]:选择含有2个BBB子元素的元素。

//*[name()='BBB']:选择所有名称为BBB的元素,等价于//BBB。

//*[starts-with(name(),'B')]:选择所有名称以"B"起始的元素。

//*[contains(name(),'C')]:选择所有名称包含"C"的元素。

//*[string-length(name())<3]:选择名字长度小于3的元素。


DOM4J中XPath的使用


1.使用XPath获取指定节点

privatestaticvoidgetNode(Documentdoc){
Nodenode=doc.selectSingleNode("/State/City/street");
System.out.println(node.getText());
}



2.使用XPath获取节点集合

privatestaticvoidgetNodes(Documentdoc){
List<Node>nodes=doc.selectNodes("/State/City");
System.out.println(nodes.size());
}



3.使用XPath获取指定属性

privatestaticvoidgetAttribute(Documentdoc){
//获取拥有Name属性的节点
Nodenode=doc.selectSingleNode("//*[@Name]");
//获取该节点的Name属性值
Stringname=node.valueOf("@Name");
System.out.println(name);
}



案例

学生信息存储

Dom4jUtils:DOM4J解析的工具类,包括获取文档对象方法和保存文件方法。

publicclassDom4jUtils{
/**
*获取XML数据的Document对象
*
*@return
*/
publicstaticDocumentgetDocument(Stringpath){
if(path==null){
returnnull;
}
//创建XML解析器
Documentdoc=null;
SAXReaderreader=newSAXReader();
try{
//解析XML文件
doc=reader.read(path);
}catch(DocumentExceptione){
//异常处理
System.out.println("读取XML失败!");
e.printStackTrace();
}
returndoc;
}
/**
*将Document对象保存到XML文件中
*
*@paramdoc要保存的Document对象
*@return
*/
publicstaticbooleansaveXml(Documentdoc,Stringpath){
if(path==null||doc==null){
returnfalse;
}
//创建保存格式
OutputFormatof=OutputFormat.createPrettyPrint();
//创建XML写入对象
XMLWriterwriter=null;
try{
//将Document对象写入到XML文件中
OutputStreamos=newFileOutputStream(newFile(path));
writer=newXMLWriter(os,of);
writer.write(doc);
}catch(IOExceptione){
//异常处理
System.out.println("文件写入错误!");
e.printStackTrace();
returnfalse;
}finally{
//资源释放
if(writer!=null){
try{
writer.close();
}catch(IOExceptione){
System.out.println("资源关闭错误!");
e.printStackTrace();
returnfalse;
}
}
}
returntrue;
}
}


config.xml:配置具体Dao的实现类名,xml数据存储路径。

<?xmlversion="1.0"encoding="UTF-8"?>
<dao>
<student>
<class>com.xml.dao.impl.StudentDaoByDom4j</class>
<db>src/com/xml/db/student.xml</db>
</student>
</dao>


student.xml:学生数据存储的xml文件。

<?xmlversion="1.0"encoding="UTF-8"?>
<students>
<studentstudentid="1255"classid="55">
<name>帅哥</name>
<gender>男</gender>
<score>90</score>
</student>
</students>


StudentDao:DAO的接口设计

packagecom.xml.dao;
importcom.xml.bean.Student;
publicinterfaceStudentDao{
/**
*添加学生信息
*@params要添加的学生对象
*@return
*/
publicbooleanadd(Students);
/**
*删除学生的信息
*@paramsid要删除的学生id
*@return
*/
publicbooleandelete(intsid);
/**
*查询学生成绩
*@paramsid要查询的学生id
*@return
*/
publicfloatgetScore(intsid);
}


StudentDaoFactory:DAO的获取工厂类,该类为枚举单例,通过config.xml的配置信息,提供获取具体DAO对象的公有方法。

packagecom.xml.dao;
importorg.dom4j.Document;
importcom.xml.util.Dom4jUtils;
publicenumStudentDaoFactory{
dao;
publicStudentDaogetInstance(){
StudentDaosdao=null;
//获取配置信息XML文档的Document对象
Documentdoc=Dom4jUtils.getDocument("bin/com/xml/config/config.xml");
//获取StudentDao的实现类名
StringclassName=doc.selectSingleNode("/dao/student/class").getText();
//创建StudentDao实现类
try{
sdao=(StudentDao)Class.forName(className).newInstance();
}catch(InstantiationException|IllegalAccessException|ClassNotFoundExceptione){
System.out.println("配置信息错误!找不到该类。");
e.printStackTrace();
}
returnsdao;
}
}


StudentDaoByDom4j:DAO的实现类,根据配置信息能够获取具体数据XML的位置,并对之操作。

packagecom.xml.dao.impl;
importorg.dom4j.Document;
importorg.dom4j.Element;
importorg.dom4j.Node;
importcom.xml.bean.Student;
importcom.xml.dao.StudentDao;
importcom.xml.util.Dom4jUtils;
publicclassStudentDaoByDom4jimplementsStudentDao{
privateDocumentdoc=null;
privateStringpath=null;
publicStudentDaoByDom4j(){
//获取配置信息XML文档的Document对象
Documentconfig=Dom4jUtils.getDocument("bin/com/xml/config/config.xml");
//获取学生信息存储路径
this.path=config.selectSingleNode("/dao/student/db").getText();
//获取学生信息XML文档的Document对象
this.doc=Dom4jUtils.getDocument(this.path);
}
@Override
publicbooleanadd(Students){
//性别预处理
String[]mask={"男","女","人妖"};
//在根节点下创建学生元素并设置属性
Elemente=doc.getRootElement().addElement("student")
.addAttribute("studentid",String.valueOf(s.getId()))
.addAttribute("classid",String.valueOf(s.getClassId()));
//为学生元素添加子元素
e.addElement("name").setText(s.getName());
e.addElement("gender").setText(mask[s.getGender()]);
e.addElement("score").setText(String.valueOf(s.getScore()));
//将Document保存到XML文件中
Dom4jUtils.saveXml(doc,this.path);
returntrue;
}
@Override
publicbooleandelete(intsid){
//获取要删除的节点
Nodenode=doc.selectSingleNode("/students/student[@studentid='"+String.valueOf(sid)+"']");
//使用父节点删除该节点
node.getParent().remove(node);
//将Document保存到XML文件中
Dom4jUtils.saveXml(doc,this.path);
returntrue;
}
@Override
publicfloatgetScore(intsid){
//获取要查询成绩的学生成绩
Stringscore=doc.selectSingleNode("/students/student[@studentid='"
+String.valueOf(sid)+"']/score").getText();
//返回成绩
returnFloat.parseFloat(score);
}
}


测试

packagecom.xml.test;
importorg.junit.Test;
importcom.xml.bean.Student;
importcom.xml.dao.StudentDao;
importcom.xml.dao.StudentDaoFactory;
publicclassStudentDaoTest{
privateStudentDaosdao=null;
{
sdao=StudentDaoFactory.dao.getInstance();
}
@Test
publicvoidtestAdd(){
Students=newStudent(1248,"苏苏",55,2,80);
sdao.add(s);
}
@Test
publicvoidtestDelete(){
sdao.delete(1248);
}
@Test
publicvoidtestGetScore(){
floatscore=sdao.getScore(1255);
System.out.println(score);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: