
引言:XML(可扩展标记语言)在软件开发工程中取得了广泛的应用。在 Java 语言中操作 XML 有许多方法,最常用的方法就是使用 JDom、Dom4j 等第三方组件。本文将简单介绍使用 Dom4j 操作 XML 的基本方法。
本文采用的 Dom4j 版本为 1.6.1,下载地址见文章结尾。 废话不多说,先来看一下本文使用的 XML 文件内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?xml version="1.0" encoding="UTF-8"?> <class id="1"> <student> <num>0001</num> <name>张三</name> <age>19</age> </student> <student> <num>0002</num> <name>李四</name> <age>21</age> <hobby> <name>足球</name> <name>篮球</name> </hobby> </student> <teacher> <name>王老师</name> <age>40</age> <course>Java</course> </teacher> </class>
|
在这个 XML 文件中,可以看到根节点为 class,它有 student 和 teacher 子节点,而 student 子节点中又包含 num、name、age、hobby 等孙子辈节点,teacher 子节点中包含 name、age、course 等孙子辈节点。 下面就使用 dom4j 来操作这个 xml 文件。
解析 XML
当使用 dom4j 操作 xml 时,你想做的第一件事可能就是解析一个 Xml 文档,这个操作在 dom4j 中十分容易,使用下面的代码即可以轻松的解析 xml 文件并返回一个 Document 对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package cn.javacodes.dom4j;
import java.io.File;
import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader;
public class TestDom4j {
public static void main(String[] args) throws Exception { SAXReader reader = new SAXReader(); Document doc = reader.read(new File("d:/DemoXML.xml")); Element root = doc.getRootElement(); System.out.println("根节点:" + root.getName() + ",id=" \+ root.attributeValue("id")); }
}
|
输出结果:
根节点:class,id = 1
使用迭代器 Iterator
一个 Element 对象可以通过几个方法来返回一个标准的 Java 迭代器: (1)迭代所有子元素
1 2 3 4 5
| for (Iterator i = root.elementIterator(); i.hasNext(); ) { Element element = (Element) i.next(); System.out.println(element.getName()); }
|
输出结果:
student student teacher
(2)通过元素名称迭代
1 2 3 4 5
| for ( Iterator i = root.elementIterator( "student" ); i.hasNext(); ) { Element foo = (Element) i.next(); System.out.println(foo.getName()); }
|
输出结果:
student student
(3)迭代所有属性
1 2 3 4 5
| for ( Iterator i = root.attributeIterator(); i.hasNext(); ) { Attribute attribute = (Attribute) i.next(); System.out.println(attribute.getName() + ":" + attribute.getValue()); }
|
输出结果:
id:1
获取元素值
通常我们都需要获取 xml 元素标签内部的文本,也就是元素值,下面一个简单的例子递归显示所有的元素值:
1 2 3 4 5 6 7 8 9 10
| public static void showAllElementText(Element e){ for (Iterator i = e.elementIterator(); i.hasNext(); ) { Element element = (Element) i.next(); if (!element.elements().isEmpty()) { showAllElementText(element); } else { System.out.println(element.getName()+"="+element.getTextTrim()); } } }
|
输出结果
num = 0001 name = 张三 age = 19 num = 0002 name = 李四 age = 21 name = 足球 name = 篮球 name = 王老师 age = 40 course = Java
使用 XPath 表达式
在 Dom4j 中使用 XPath 表达式可以更加轻松的操作 XML 文档,使用 XPath 表达式可以使用仅一行代码来进行复杂的操作,在 Dom4j 中使用 XPath 的几个简单示例代码如下: (1)查询单个节点(默认查找第一个):
1 2 3 4 5 6 7 8
| SAXReader reader = new SAXReader();
Document doc = reader.read(new File("d:/DemoXML.xml"));
Node node = doc.selectSingleNode("//student/name");
System.out.println(node.getName() + "=" + node.getText());
|
(2)查询多个节点
1 2 3 4 5 6 7
| List<Node> list = doc.selectNodes("//student");
for (Node node : list) { System.out.println(node.getName() \+ ":" \+ node.valueOf("name")); }
|
以上为两种经常使用的方法,另外如果你想在一个 XHTML 文档中查找到所有的超文本链接,可以使用下面这个窍门轻松实现:
1 2 3 4 5 6 7
| public void findLinks(Document document) throws DocumentException { List list = document.selectNodes( "//a/@href" ); for (Iterator iter = list.iterator(); iter.hasNext(); ) { Attribute attribute = (Attribute) iter.next(); String url = attribute.getValue(); } }
|
如果你需要任何有关学习 XPah 表达式语言的帮助,你可以访问 Zvon tutorial进行学习,这里可以通过各种各样的例子帮助你学习。
快速循环
如果你需要操作一个十分庞大的 XML 文档,那么你应该使用快速循环的方法以避免在每次循环都创建 Iterator 对象,下面是一个简单的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public void treeWalk(Document document) { treeWalk( document.getRootElement() ); }
public void treeWalk(Element element) { for ( int i = 0, size = element.nodeCount(); i < size; i++ ) { Node node = element.node(i); if ( node instanceof Element ) { treeWalk( (Element) node ); } else { } } }
|
创建 XML Document 对象
在使用 Dom4j 时经常需要创建一个新的 document,下面是一个简单的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element;
public class Foo {
public Document createDocument() { Document document = DocumentHelper.createDocument(); Element root = document.addElement( "root" );
Element author1 = root.addElement( "author" ) .addAttribute( "name", "James" ) .addAttribute( "location", "UK" ) .addText( "James Strachan" ); Element author2 = root.addElement( "author" ) .addAttribute( "name", "Bob" ) .addAttribute( "location", "US" ) .addText( "Bob McWhirter" );
return document; } }
|
写入 XML 文件
使用 Dom4j 将 Document 对象写入到 XML 文件十分简单,你只需要 1 行代码即可解决:
1
| document.write( new FileWriter( "foo.xml" ));
|
如果你想修改输出的格式,例如更易读的排版或者压缩(紧凑)的排版,再或者你想通过 Writer 或 OutputStream 进行输出,那么你可以使用 XMLWriter 类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import org.dom4j.Document; import org.dom4j.io.OutputFormat; import org.dom4j.io.XMLWriter;
public class Foo {
public void write(Document document) throws IOException {
XMLWriter writer = new XMLWriter( new FileWriter( "output.xml" ) ); writer.write( document ); writer.close();
OutputFormat format = OutputFormat.createPrettyPrint(); writer = new XMLWriter( System.out, format ); writer.write( document );
format = OutputFormat.createCompactFormat(); writer = new XMLWriter( System.out, format ); writer.write( document ); } }
|
Document 对象与 XML 代码互转
如果你想通过一个 Document 对象或其他任何节点对象(例如 Attribute 或 Element),你可以通过 asXML () 方法将它转换为 XML 文本字符串,例如:
1 2
| Document document = ...; String text = document.asXML();
|
如果你想从一个 XML 文本字符串转为一个 Document 对象,你可以使用 DocumentHelper.parseText() 方法进行解析:
1 2
| String text = "<person> <name>James</name> </person>"; Document document = DocumentHelper.parseText(text);
|
XSLT
通过 Sum 公司提供的 JAXP API 在一个 Document 上应用 XSLT 十分简单。这里有一个使用 JAXP 创建一个 transformer 并应用到 Document 上的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory;
import org.dom4j.Document; import org.dom4j.io.DocumentResult; import org.dom4j.io.DocumentSource;
public class Foo {
public Document styleDocument( Document document, String stylesheet ) throws Exception {
TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer( new StreamSource( stylesheet ) );
DocumentSource source = new DocumentSource( document ); DocumentResult result = new DocumentResult(); transformer.transform( source, result );
Document transformedDoc = result.getDocument(); return transformedDoc; } }
|