引言: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; } }