情景切入:
最近学校老师布置一个小作业,要求使用dom4j将xml文件转换成project.properties配置文件和Excel表格:
如XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<books type="名著">
<book name="三国演义" author="罗贯中">
<info>三国简介</info>
</book>
<book name="红楼梦" author="曹雪芹">
<info>红楼简介</info>
</book>
</books>
<books type="小说">
<book name="斗罗大陆" author="唐家三少">
<info>斗罗简介</info>
</book>
<book name="诛仙" author="萧鼎">
<info>诛仙简介</info>
</book>
</books>
</root>
要求转换成形如此的配置文件:
此处先就生成此配置文件做一些个人的小结,仅供参考交流学习。
正文:
准备阶段:
要想使用dom4j解析xml文件就必须有dom4j的开发环境,由于javaSE中是不含有dom4j的接口的,因此需要手动添加dom4j的jar文件。
考虑受众可能不知道怎样使用Eclipse导入jar文件,这里做一个简要介绍步骤:
1、创建一个工程
2、建立一个jar文件夹用来存放dom4j.jar文件(如图)
3、将dom4j.jar文件直接拖拽进jar文件夹(RT)
4、将此java包添加进入工程,步骤如下。
5、当你看到如下图效果时,恭喜你,你已经可以进行编程了。
好了,环境配好了,可以继续往下进行了。
要想使用dom4j来解析xml文件,首先要弄懂两件事(不懂也得知道怎么用的):
1、xml的结构特点
2、dom4j的api
下面逐一分析:
1、xml的机构特点
以上面的xml文件为例,其意义上可以看作是是一个树型结构,总体上是这个样子
Root有两个子节点books,每个books又各有两个子节点book,每个book节点下各有一个子节点info。
而type、name、author等,虽然再文件中也要生成,但他们并不是一个节点,而是这些节点的属性,而属性的调用在dom4j中也有相应的方法。
这个结构就暂且说到这,主要是为了讲dom4j的方法好理解一些才涉及的。2、dom4j的API
dom4j的主要接口有:
Attribute | Attribute定义了XML的属性 |
Branch | Branch为能够包含子节点的节点如XML元素(Element)和文档(Docuemnts)定义了一个公共的行为, |
CDATA | CDATA定义了XML CDATA 区域 |
CharacterData | CharacterData是一个标识接口,标识基于字符的节点。如CDATA,Comment, Text. |
Comment | Comment定义了XML注释的行为 |
Document | Document定义了XML文档 |
DocumentType | DocumentType定义XML DOCTYPE声明 |
Element | Element定义XML 元素 |
ElementHandler | ElementHandler定义了 Element 对象的处理器 |
ElementPath | ElementPath被 ElementHandler 使用,用于取得当前正在处理的路径层次信息 |
Entity | Entity定义 XML entity |
Node | Node为所有的dom4j中XML节点定义了多态行为 |
NodeFilter | NodeFilter 定义了在dom4j节点中产生的一个滤镜或谓词的行为(predicate) |
ProcessingInstruction | ProcessingInstruction 定义 XML 处理指令 |
Text | Text 定义XML 文本节点 |
Visitor | Visitor 用于实现Visitor模式 |
XPath | XPath 在分析一个字符串后会提供一个XPath表达式 |
实际上,这些接口的命名都是根据他的功能来命名的,看到名字大概也能猜到其作用了吧。
由于dom4j内容很大,而且要完成以上任务根本不需要了解这么多,感兴趣的话可以点击一下连接,里面有dom4j的详细介绍。点击打开链接
我们这里就只抽其需要的做一下拼接就能完成任务了。
我们需要的就只有Document接口Element接口和Attribute接口,就这三个就足够了,是不是够简单啊?
Document接口:
SAXReader reader = new SAXReader();
Document document = reader.read(newFile(xmlAddress));
- @使用SAXReader创建一个reader对象,通过此对象可以读取xml文件存在Document的对象中
- @xmlAddress:xml文件的地址,如 "src/demo/books.xml"
Element接口:
Element root=document.getRootElement();
- @通过Document对象的.getRootElement()方法可以获取根节点<root>
- @此处的root就代表了上面树图中的第一个节点。只有通过他,我们才能往下解析,得到更远节点的属性名和值。
Element element=root.element("books");
List elemBooksList=root.elements();
由于elements()的返回值为List<Element>,应该定义一个List数组储存。
- elemBooksList.get(int index) //得到List中第index个元素(index从0开始)
- elemBooksList.size() //得到List的大小
Iterator iterator=root.elementIterator();
通过他得到的是root下所有直接节点的一个迭代器,使用迭代器你就能对这个两个books节点做遍历了。
- 通过iterator.hasNext();判断是否迭代器中还有元素,如果有就进入迭代,如果没有就跳出
- 通过iterator.next();取出此迭代器中的接下来的一个元素
- 要遍历此树中的所有节点就要用到数据结构的线序遍历思想和递归方法,这个在接下来的内容中涉及
String elementName=element.getName();
通过getName()方法可以获得当前节点的节点名,如上图文件中的[root,books,book,info]这些值。
String nodeText=element.getText();
通过getText()方法可以得到当前节点的节点中的内容,如上图文件中的[
三国简介,红楼简介。。。]
Attribute attribute=book.attribute("name");
List attList =elem.attributes();
同上2号function。
Iterator iterator=book.attributeIterator();
通过他得到的是book节点中
所有属性
的一个迭代器,同意你可以迭代遍历book的几个属性[name,author]
Attribute接口:
Attribute attribute=book.attribute("name");
- 同Element对象一样,Attribute对象也有getName()和getText()方法,分别得到属性的名字和属性值。
File toPro=new File("src/demo/project1.properties");
BufferedWriter bw=new BufferedWriter(new FileWriter(toPro));
bw.write("要输出的String"); //...........此处省略若干代码............
bw.newLine(); //换行
bw.close(); //关闭流
下面来看看代码实现吧:
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class dom4jTest {
public static void main(String[] args) {
String xmlAddress="src/demo/books.xml";
String toProAddess="src/demo/project.properties";
readXML(xmlAddress,toProAddess);
}
static void readXML(String xmlAddress,String toProAddess){
try {
SAXReader reader = new SAXReader();
Document document = reader.read(new File(xmlAddress));
File toPro=new File(toProAddess);
BufferedWriter bw = new BufferedWriter(new FileWriter(toPro));
Element root =document.getRootElement(); //获取根节点root
String date="【生产时间:"+(new Date()).toString()+"】";
System.out.println(date);
bw.write(date); //写入日期
bw.newLine();
List elemBooksList=root.elements();
for (int i = 0; i < elemBooksList.size(); i++) {
Element elemBooks=(Element) elemBooksList.get(i);
List attBooksList =elemBooks.attributes();
for (int j = 0; j < attBooksList.size(); j++) {
Attribute att=(Attribute)attBooksList.get(j);
// System.out.println("root.books.["+att.getName()+"]="+att.getText());
bw.write("root.books.["+att.getName()+"]="+att.getText());
bw.newLine();
}
List elemBookList=elemBooks.elements();
for (int m = 0; m < elemBookList.size(); m++) {
Element elemBook=(Element) elemBookList.get(m);
List attBookList =elemBook.attributes();
for (int n = 0; n < attBookList.size(); n++) {
Attribute att=(Attribute)attBookList.get(n);
// System.out.println("root.books.book.["+att.getName()+"]="+att.getText());
bw.write("root.books.book.["+att.getName()+"]="+att.getText());
bw.newLine();
}
Element elemBookInfo=(Element) elemBook.element("info");
// System.out.println("root.books.book."+elemBookInfo.getName()+"="+elemBookInfo.getText());
bw.write("root.books.book."+elemBookInfo.getName()+"="+elemBookInfo.getText());
bw.newLine();
}
}
bw.close();
} catch (DocumentException e) {
System.out.println("xml文件读取失败。");
} catch (IOException e) {
System.out.println("IO故障。");
}
}
}