XML编程总结(四)——使用dom4j方式操作xml

(四)使用dom4j方式操作xml

dom4j是解析XML的一种开源API,是jdom的升级品,用来读写XML文档。它具有性能优异、功能强大和极易使用的特点,它的性能超过sun公司官方的dom技术。dom4j对Xpath有良好的支持(使用xpath时需要导入jaxen的jar包),dom4j最大的特色使用大量的接口。使用dom4j时需要导入dom4j-xxx.jar包。

Attribute ——Attribute定义了XML的属性

Branch ——Branch为能够包含子节点的节点如XML元素(Element)和文档(Docuemnts)定义了一个公共的行为,

CDATA ——CDATA 定义了XML CDATA 区域

CharacterData——CharacterData是一个标识接口,标识基于字符的节点。如CDATA,Comment, Text.

Comment—— Comment 定义了XML注释的行为

Document—— 定义了XML文档

DocumentType—— DocumentType 定义XML DOCTYPE声明

Element—— Element定义XML 元素

ElementHandler ——ElementHandler定义了 Element 对象的处理器

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表达式

测试类代码:

  1 public class Dom4jTest {
  2     private Document doc;
  3 
  4     @Before
  5     public void setUp() throws Exception {
  6         // 获得xml文档的输入流对象
  7         InputStream is = Dom4jTest.class.getClassLoader().getResourceAsStream("books.xml");
  8         // 创建SAXReader对象
  9         SAXReader reader = new SAXReader();
 10         // 通过流对象解析xml文档为Document对象
 11         doc = reader.read(is);
 12     }
 13 
 14     /**
 15      * 使用节点迭代器查询元素
 16      * @throws Exception
 17      */
 18     @Test
 19     public void testRetrieve() throws Exception {        
 20         //获得文档的根节点
 21         Element rootElement = doc.getRootElement();
 22         Iterator iterator = rootElement.elementIterator();
 23         while(iterator.hasNext()){
 24             //获得子节点,先转换为Element,有更多的方法
 25             Element element = (Element) iterator.next();
 26             String value = element.attributeValue("category");
 27             //获得属性为CHILDREN的book节点
 28             if("CHILDREN".equals(value)){
 29                 //获得book节点的迭代器
 30                 Iterator childIterator = element.elementIterator();
 31                 while(childIterator.hasNext()){
 32                     Node node = (Node) childIterator.next();
 33                     //获取子节点的名称
 34                     String name = node.getName();
 35                     if("price".equals(name)){
 36                         //获取节点的文本
 37                         String text = node.getText();
 38                         System.out.println(text);
 39                     }
 40                 }
 41             }
 42         }
 43     }
 44     
 45     /**
 46      * 使用访问器来读取xml文档节点
 47      * @throws Exception
 48      */
 49     @Test
 50     public void testRetrieveByVisitor() throws Exception{
 51         //获得xml文档的输入流对象
 52         InputStream is = Dom4jTest.class.getClassLoader().getResourceAsStream("books.xml");
 53         // 创建SAXReader对象
 54         SAXReader reader = new SAXReader();
 55         // 通过流对象解析xml文档为Document对象
 56         Document doc = reader.read(is);
 57         // 获得文档的根节点
 58         Element rootElement = doc.getRootElement();
 59         //创建自定义的Visitor对象
 60         Visitor visitor = new DomVisitor();
 61         //使用visitor查询文档
 62         rootElement.accept(visitor);
 63     }
 64     
 65     /**
 66      * 创建新的xml文档
 67      * @throws Exception
 68      */
 69     @Test
 70     public void testCreate() throws Exception{
 71         //第一种,创建Document的方法(org.dom4j.Document)
 72         //第一种创建方式是对第二种创建方式的封装
 73         Document document = DocumentHelper.createDocument();
 74         //第二种,创建Document的方法(org.dom4j.Document)
 75         //Document doc = DocumentFactory.getInstance().createDocument();
 76         
 77         //创建根元素节点
 78         Element rootElement = document.addElement("bookstore");
 79         //创建book节点及其子节点
 80         Element bookElement = rootElement.addElement("book");
 81         bookElement.addAttribute("CATEGORY", "CODING");
 82         Element title=bookElement.addElement("title");
 83         title.setText("JAVA CODING");
 84         Element author=bookElement.addElement("author");
 85         author.setText("zs");
 86         Element year=bookElement.addElement("year");
 87         year.setText("2010");
 88         Element price=bookElement.addElement("price");
 89         price.setText("69");
 90         //打印到控制台
 91         writeToConsole(document);
 92         //输出到文件
 93         writeToFile(document);
 94     }
 95     
 96     //输出到文件
 97     private void writeToFile(Document document) throws IOException {
 98         //创建美化格式
 99         OutputFormat format=OutputFormat.createPrettyPrint();
100         XMLWriter writer=new XMLWriter
101                 (new FileWriter(new File("abook.xml")),format);
102         writer.write(document);
103         //关闭writer就会清空缓存
104         writer.close();
105     }
106 
107     //打印到控制台
108     private void writeToConsole(Document document) throws IOException {
109         //创建输出字符流
110         PrintWriter writer=new PrintWriter(System.out);
111         document.write(writer);
112         //关闭writer就会清空缓存,才会输出来
113         writer.close();
114     }
115     
116     /**
117      * 使用XPath查找节点,xpath序号从1开始
118      * 要使用dom4j的xpath支持,需要导入jaxen包
119      */
120     @Test
121     public void testXPath() throws Exception{
122         //获得属性web的book节点
123         Node node = doc.selectSingleNode("//book[@category='WEB']");
124         //获得所有的book节点
125         List nodes = doc.selectNodes("//book");
126         //获得第2个book节点
127         Node secondNode = doc.selectSingleNode("//book[2]");
128         //将xml片段转换为字符串
129         String xml = secondNode.asXML();
130         System.out.println(xml);
131     }
132     
133     @Test
134     public void testStringToXML() throws Exception{
135         String xmlString="<book category='CHILDREN'><title lang='en'>Harry Potter</title>"+
136                     "<author>J K. Rowling</author><year>2005</year><price>29.99</price></book>";
137         //转换字符串为xml片段
138         Document document = DocumentHelper.parseText(xmlString);
139         //打印到控制台
140         writeToConsole(document);
141     }
142     
143     /**
144      * 删除指定的节点
145      * @throws Exception
146      */
147     @Test
148     public void testDelete() throws Exception{
149         //获得最后一个book节点
150         Node node = doc.selectSingleNode("//book[4]");
151         //获得最后一个book节点的父节点
152         Element parent = node.getParent();
153         //删除最后一个book节点,删除需要使用父节点来删除,删除成功则返回true
154         Boolean flag=parent.remove(node);
155         System.out.println(flag);
156         //打印到控制台
157         writeToConsole(doc);
158     }
159     
160     /**
161      * 修改指定的节点
162      * @throws Exception
163      */
164     @Test
165     public void testUpdate() throws Exception{
166         //获得第一个book节点的price和year
167         Node yearNode = doc.selectSingleNode("//book[1]/year");
168         yearNode.setText("2015");
169         Node priceNode = doc.selectSingleNode("//book[1]/price");
170         priceNode.setText("59.00");
171         //修改后的xml文档打印到控制台
172         writeToConsole(doc);
173     }
174 }

Visitor子类代码:

 1 public class DomVisitor extends VisitorSupport {
 2     // 使用栈这个数据结构来保存
 3     private Stack<String> stack = new Stack<String>();
 4 
 5     // 数据
 6     private String attr;
 7     private String title;
 8     private String author;
 9     private String year;
10     private double price;
11 
12     @Override
13     public void visit(Document document) {
14     }
15 
16     @Override
17     public void visit(Element node) {
18 //        System.out.println("element node-----------");
19 
20         //获得节点的名称
21         String name = node.getName();
22         if("book".equals(name)){
23             if(!stack.isEmpty()){
24                 stack.clear();
25             }
26             stack.push(name);
27         }else if("title".equals(node.getName())){
28             stack.push(name);
29         }else if("author".equals(name)){
30             stack.push(name);
31         }else if("year".equals(name)){
32             stack.push(name);
33         }else if("price".equals(name)){
34             stack.push(name);
35         }
36     }
37 
38     @Override
39     public void visit(Attribute node) {
40 //        System.out.println("attribute node-----");
41         
42         String peek = stack.peek();
43         if("book".equals(peek)){
44             String value = node.getValue();
45             if("CHILDREN".equals(value)){
46                 attr=value;
47             }
48         }
49     }
50 
51     @Override
52     public void visit(Text node) {
53 //        System.out.println("text node--------");
54         //注意:一个标签元素前后都有一个文本节点
55         if("CHILDREN".equals(attr)){
56             String tag = stack.peek();
57             if ("title".equals(tag) && null==title)
58             {
59                 title = node.getText();
60             }
61             else if ("author".equals(tag) && null==author)
62             {
63                 author = node.getText();
64             }
65             else if ("year".equals(tag) && null==year)
66             {
67                 year = node.getText();
68             }
69             else if ("price".equals(tag) && price==0)
70             {
71                 price = Double.parseDouble(node.getText());
72                 System.out.println(this.toString());                
73             }
74         }        
75     }
76 
77     @Override
78     public String toString() {
79         StringBuilder sb=new StringBuilder();
80         sb.append("book attribute:"+attr);
81         sb.append("
");
82         sb.append("title:"+title);
83         sb.append("
");
84         sb.append("author:"+author);
85         sb.append("
");
86         sb.append("year:"+year);
87         sb.append("
");
88         sb.append("price:"+price);
89         sb.append("
");
90         return sb.toString();
91     }
92 }

使用Visitor子类读取文档结果:

book attribute:CHILDREN

title:Harry Potter

author:J K. Rowling

year:2005

原文地址:https://www.cnblogs.com/techlogy/p/5965096.html