使用Dom4j解析XML文档

1.Dom4j简介

  • Dom4j是一个简单、灵活的开放源代码的库。Dom4j是由早期开发JDOM的人分离出来而后独立开发的。与JDOM不同的是,dom4j使用接口和抽象基类,虽然Dom4j的API相对要复杂一些,但它提供了比JDOM更好的灵活性。
  • Dom4j是一个非常优秀的Java XML的API,具有性能优异、功能强大和极易使用的特点。现在很多软件采用的Dom4j,例如Hibernate,包括sun公司自的JAXM也用了Dom4j。
  • 使用Dom4j开发,需下载dom4j相应的jar文件。可前往https://dom4j.github.io/进行相应版本的下载,在这里LZ选择了dom4j-2.1.0进行了下载。
2.使用Dom4j获取Document对象
在Dom4j中获取Document对象的方式有三种:
//1.读取XML文件,获得document对象 SAXReader reader = new SAXReader(); Document document = reader.read("src/book.xml"); //2.解析XML形式的文本,得到document对象. String text = "<书名>"; Document document = DocumentHelper.parseText(text); //3.主动创建document对象. Document document = DocumentHelper.createDocument(); //创建根节点 Element root = document.addElement("members");

3.使用Dom4j对xml文档进行基本操作
【使用Dom4j解析XML文档】xml代码示例:
<书架> <书> <书名 name="jxs">大话数据结构 <作者>程杰 <售价>38.00 <书> <书名>MySQL必知必会 <作者>Ben Forta <售价>23.00

基本操作代码示例:
package dom4j; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; import org.junit.Test; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; /** * Created by jiangxs on 2017/10/11. * 使用dom4j对xml文档进行解析 * CRUD */ public class Foo {/** * 遍历xml文档中的所有标签 * */ @Test public void listTag() throws DocumentException { SAXReader reader = new SAXReader(); Document document = reader.read("src/book.xml"); Element element = document.getRootElement(); list(element); }public void list(Element element){ System.out.println(element.getName()); List list = element.elements(); for (Element child : list){ list(child); } }/** * 获取<书名 name="jxs">大话数据结构节点内容 * */ @Test public void test1() throws DocumentException { SAXReader reader = new SAXReader(); Document document = reader.read("src/book.xml"); String text = document.getRootElement().element("书").element("书名").getText(); System.out.println(text); }/** * 获取<书名 name="jxs">大话数据结构节点内容 * */ @Test public void test2() throws DocumentException { SAXReader reader = new SAXReader(); Document document = reader.read("src/book.xml"); Element bookName = document.getRootElement().element("书").element("书名"); System.out.println(bookName.attributeValue("name")); }/** * 向xml文档中添加一个售价节点 * */ @Test public void test3() throws DocumentException, IOException { SAXReader reader = new SAXReader(); Document document = reader.read("src/book.xml"); //创建需要添加的节点 Element element = DocumentHelper.createElement("售价"); element.setText("39.00"); //把节点挂到书下 document.getRootElement().element("书").add(element); //使用pretty使生成的新节点按格式排列 OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); //把更新内容写到xml下 //使用字节流不会由于两边格式不一致而出现乱码 XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format); writer.write(document); writer.close(); }/** * 向xml文档中指定位置删除一个售价节点 * */ @Test public void test5() throws DocumentException, IOException { SAXReader reader = new SAXReader(); Document document = reader.read("src/book.xml"); //选择需要删除的节点 Element element = document.getRootElement().element("书").elements("售价").get(1); element.getParent().remove(element); //刷新 OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format); writer.write(document); writer.close(); }/** * 向xml文档中指定位置修改一个售价节点 * */ @Test public void test6() throws DocumentException, IOException { SAXReader reader = new SAXReader(); Document document = reader.read("src/book.xml"); //选择需要修改的节点进行修改 Element element = document.getRootElement().element("书").elements("售价").get(1); element.setText("55.00"); //刷新 OutputFormat format = OutputFormat.createPrettyPrint(); format.setEncoding("UTF-8"); XMLWriter writer = new XMLWriter(new FileOutputStream("src/book.xml"),format); writer.write(document); writer.close(); } }

4.XPath的基本语法
下面的语法基于该xml文档
<书架> <书> <书名 name="jxs">大话数据结构 <作者>程杰 <售价>88.00 <售价>55.00 <书> <书名 name="sxj">MySQL必知必会 <作者>Ben Forta <售价>23.00

选取节点
表达式 描述
nodename 选取此节点的所有子节点
/ 从根节点选取
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
. 选取当前节点
.. 选取当前节点的父节点
@ 选取属性
应用上述表格
路径表达式 结果
书架 选取”书架”元素的所有子节点
/书架 选取根元素”书架”(假如路径起始于正斜杠(/),则此路径始终代表到某元素的绝对路径)
书架/书 选取书架的子元素所有书元素
//书 选取所有书子元素,而不管它们在文档中的位置
书架//书 选择属于书架元素的后代的所有书元素,而不管它们位于书架之下的什么位置
@name 选取名为name的所有属性
谓语(Predicates) 谓语用来查找某个特定的节点或者包含某个指定的值的节点。
谓语被嵌在方括号中。
在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:
路径表达式 结果
/书架/书[1] 选取属于 书架 子元素的第一个 书 元素
/书架/书[last()] 选取属于 书架 子元素的最后一个 书 元素
/书架/[last()-1] 选取属于 书架 子元素的倒数第二个 书 元素
/书架/书[position()<3] 选取最前面的两个属于 书架 元素的子元素的 书 元素。
//书名[@name] 选取所有拥有名为 name 的属性的 书名 元素
//书名[@name=’jxs’] 选取所有 书名 元素,且这些元素拥有值为 jxs 的 name 属性。
/书架/书[售价>30] 选取 书架 元素的所有 书 元素,且其中的 售价 元素的值须大于 30.00。
/书架/书[售价>30.00]/书名 选取 书架 元素中的 书 元素的所有 书名 元素,且其中的 售价 元素的值须大于 30.00。
选取未知节点 XPath 通配符可用来选取未知的 XML 元素。
通配符 描述
* 匹配任何元素节点
@* 匹配任何属性节点
node() 匹配任何类型的节点
下面表格列出了一些路径表达式,以及这些表达式的结果:
路径表达式 结果
/书架/* 选取 书 元素的所有子元素
//* 获取文档中的所有元素
//title[@*] 选取所有带属性的title元素
选取若干路径 通过在路径表达式中使用”|”运算符可以选取若干个路径。
XPath小例子 示例程序1:
改代码的xml文件用的上述xml文件
package dom4j; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.io.SAXReader; import org.junit.Test; /** * Created by jiangxs on 2017/10/16. * 在dom4j中使用XPath */ public class XpathDemo {@Test public void test1() throws DocumentException { SAXReader reader = new SAXReader(); Document document = reader.read("src/book.xml"); //选择要查找的内容 Element element = (Element) document.selectNodes("//作者").get(0); System.out.println(element.getText()); } }

示例程序2:

package dom4j; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.Node; import org.dom4j.io.SAXReader; import org.junit.Test; /** * Created by jiangxs on 2017/10/16. * 在dom4j中使用XPath */ public class XpathDemo {@Test public void test2() throws DocumentException { String name = "王五"; String password = "123"; SAXReader reader = new SAXReader(); Document document = reader.read("src/userlogging.xml"); Node node = document.selectSingleNode("//user[@username='"+name+"' and @password='"+password+"']"); if (node != null) System.out.println("登录成功!欢迎您!"); else System.out.println("登录名或密码错误,登录失败,请重试!"); } }

示例程序2演示结果:
登录成功!欢迎您!Process finished with exit code 0

    推荐阅读