XML解析

Dom4j工具

使用步骤:

                1)导入dom4j的核心包。 dom4j-1.6.1.jar(点击下载)

               2)编写Dom4j读取xml文件代码​

相关方法

节点:

Iterator  Element.nodeIterator();  //获取当前标签节点下的所有子节点

标签:

Element  Document.getRootElement();  //获取xml文档的根标签           

Element   ELement.element("标签名") //指定名称的第一个子标签

Iterator<Element> Element.elementIterator("标签名");// 指定名称的所有子标签

List<Element>       Element.elements(); //获取所有子标签                                      

属性:

String   Element.attributeValue("属性名") //获取指定名称的属性值

Attribute    Element.attribute("属性名");//获取指定名称的属性对象      

Attribute.getName()  //获取属性名称

Attibute.getValue()  //获取属性值

List<Attribute>      Element.attributes();  //获取所有属性对象

Iterator<Attribute>              Element.attibuteIterator(); //获取所有属性对象

文本:

Element.getText();  //获取当前标签的文本

Element.elementText("标签名") //获取当前标签的指定名称的子标签的文本内容

 Dom4j修改xml文档

 (1)写出内容到xml文档

     XMLWriter writer = new XMLWriter(OutputStream, OutputForamt)

     wirter.write(Document);

(2)常用方法

增加

Ø  DocumentHelper.createDocument();  增加文档

Ø  addElement(名称) 增加标签            

Ø  addAttribute(名称,值)  增加属性

修改

Ø  Attribute.setValue(值)

Ø  Element.addAttribute(属性名,值)

Ø  Element.setText(内容) 

删除

Ø  Element.detach()

Ø  Attribute.detach()

SAX解析工具

核心的API:

     SAXParser类: 用于读取和解析xml文件对象

     parse(File f, DefaultHandler dh)方法: 参数一: File:表示 读取的xml文件。

                                                                 参数二: DefaultHandler: SAX事件处理程序。使用DefaultHandler的子类[一个类继承class 类名(extends DefaultHandler)  在调用是创建传进去

例如:

1
2
3
4
5
6
//创建SAXParser对象
               SAXParser parser=SAXParserFactory.newInstance().newSAXParser();
//调用parse方法
             parser.parse( new  File( "./src/contact.xml" ),  new  MyDefaultHandler());

  

 DefaultHandler类的API:

        void startDocument()  :  在读到文档开始时调用

           void endDocument()  :在读到文档结束时调用

           void startElement(String uri, String localName, String qName, Attributes attributes)  :读到开始标签时调用                                    

        void endElement(String uri, String localName, String qName)   :读到结束标签时调用

           void characters(char[] ch, int start, int length)  : 读到文本内容时调用

比较两者之间的区别

DOM解析

SAX解析

原理: 一次性加载xml文档,不适合大容量的文件读取

原理: 加载一点,读取一点,处理一点。适合大容量文件的读取

DOM解析可以任意进行增删改成

SAX解析只能读取

DOM解析任意读取任何位置的数据,甚至往回读

SAX解析只能从上往下,按顺序读取,不能往回读

DOM解析面向对象的编程方法(Node,Element,Attribute),Java开发者编码比较简单。

SAX解析基于事件的编程方法。java开发编码相对复杂。

xPath技术

(1)xPath的作用: 主要是用于快速获取所需的节点对象 ( 在dom4j中如何使用xPath技术)

(2)步骤及方法

导入xPath支持jar包 。  jaxen-1.1-beta-6.jar(点击下载)

使用xpath方法

List<Node>  selectNodes("xpath表达式");   查询多个节点对象

Node       selectSingleNode("xpath表达式");  查询一个节点对象

(3)xPath语法

/      绝对路径      表示从xml的根位置开始或子元素(一个层次结构)

//     相对路径       表示不分任何层次结构的选择元素。

*      通配符         表示匹配所有元素

[]      条件           表示选择什么条件下的元素

@  属性  表示选择属性节点  //BBB[@name='bbb']  选择含有属性name且其值为'bbb'的BBB元素 

and     关系          表示条件的与关系(等价于&&)

text()    文本           表示选择文本内容

 

实例练习

创建一个通讯录,有联系人的各种信息,在控制台有一些功能,及具体实现效果如图

对应生成的xml文件

 

 

 

首先,分解下一下,既然是一个联系人,有众多属性,我们可以考略通过创建一个Contact类同时将其封装,如下:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package  com.gqx.Test;
public  class  Contact {
     private  String Id;
     private  String name;
     private  String sex;
     private  String age;
     private  String phone;
     private  String qq;
     private  String email;
     public  String getId() {
         return  Id;
     }
     public  void  setId(String id) {
         Id = id;
     }
     public  String getName() {
         return  name;
     }
     public  void  setName(String name) {
         this .name = name;
     }
     public  String getSex() {
         return  sex;
     }
     public  void  setSex(String sex) {
         this .sex = sex;
     }
     public  String getAge() {
         return  age;
     }
     public  void  setAge(String age) {
         this .age = age;
     }
     public  String getPhone() {
         return  phone;
     }
     public  void  setPhone(String phone) {
         this .phone = phone;
     }
     public  String getQq() {
         return  qq;
     }
     public  void  setQq(String qq) {
         this .qq = qq;
     }
     public  String getEmail() {
         return  email;
     }
     public  void  setEmail(String email) {
         this .email = email;
     }
     @Override
     public  String toString() {
         return  "Contact [Id="  + Id +  ", name="  + name +  ", sex="  + sex
                 ", age="  + age +  ", phone="  + phone +  ", qq="  + qq
                 ", email="  + email +  "]" ;
     }
}

  

其次考略到改程序额主菜单这些目录实现的操作比较复杂,不能一起堆放在主程序中,这时可以考虑创建一个抽象的接口将目录功能做一个汇总,

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package  com.gqx.Test;
import  java.io.FileNotFoundException;
import  java.io.UnsupportedEncodingException;
import  java.util.List;
import  org.dom4j.DocumentException;
public  interface  ContactOperate {
     public  void  addContact(Contact contact)  throws  Exception;
     public  void  ModifyContact(Contact contact)  throws  Exception;
     public  void  removeContact(String id)  throws  Exception;
     public  List<Contact>  checkContacts();
}

  

这个时候我们就可以写出主程序了,虽然上面接口的具体方法,我们还没有实现,我们先把框架搭好

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package  com.gqx.Test;
import  java.io.BufferedReader;
import  java.io.IOException;
import  java.io.InputStreamReader;
import  java.util.List;
import  java.util.Scanner;
public  class  Menu {
     public  static  void  main(String[] args)  throws  Exception {
         // TODO Auto-generated method stub
         Scanner bf= new  Scanner(System.in);
         //创建接口,同时对实例化它的实现接口
         ContactOperate operator= new  Operator();
         while  ( true ) {
             //看到菜单
             printMenu();
             //读取用户输入
             int  command=Integer.parseInt(bf.nextLine());
             switch  (command) {
             case  1 :
                 //1、添加联系人
                 Contact contact= new  Contact();
                 System.out.println( "请输入联系人姓名:" );
                 String name=bf.nextLine();
                 contact.setName(name);
                 System.out.println( "请输入联系人ID:" );
                 String id=bf.nextLine();
                 contact.setId(id);
                 System.out.println( "请输入联系人性别:" );
                 String sex=bf.nextLine();
                 contact.setSex(sex);
                 System.out.println( "请输入联系人年龄:" );
                 String age=bf.nextLine();
                 contact.setAge(age);
                 System.out.println( "请输入联系人电话:" );
                 String phone=bf.nextLine();
                 contact.setPhone(phone);
                 System.out.println( "请输入联系人邮箱:" );
                 String email=bf.nextLine();
                 contact.setEmail(email);
                 System.out.println( "请输入联系人qq:" );
                 String qq=bf.nextLine();
                 contact.setQq(qq);
                 System.out.println(contact);
                 operator.addContact(contact);
                 break ;
             case  2 :
                 Contact contact1= new   Contact();
                 
                 System.out.println( "请输入要修改的联系人ID:" );
                 String id1=bf.nextLine();
                 contact1.setId(id1);
                 System.out.println( "请输入修改联系人姓名:" );
                 String name1=bf.nextLine();
                 contact1.setName(name1);
                 
                 System.out.println( "请输入修改联系人性别:" );
                 String sex1=bf.nextLine();
                 contact1.setSex(sex1);
                 System.out.println( "请输入修改联系人年龄:" );
                 String age1=bf.nextLine();
                 contact1.setAge(age1);
                 System.out.println( "请输入修改联系人电话:" );
                 String phone1=bf.nextLine();
                 contact1.setPhone(phone1);
                 System.out.println( "请输入修改联系人邮箱:" );
                 String email1=bf.nextLine();
                 contact1.setEmail(email1);
                 System.out.println( "请输入修改联系人qq:" );
                 String qq1=bf.nextLine();
                 contact1.setQq(qq1);
                 operator.ModifyContact(contact1);
                 break ;
             case  3 :
                 //删除联系人
                 String idString=bf.nextLine();
                 operator.removeContact(idString);
                 operator.removeContact(idString);
                 break ;
             case  4 :
                 //查看所有联系人
                 List<Contact> contacts=operator.checkContacts();
                 for  (Contact contact2 : contacts) {
                     System.out.println(contact2);
                 }
                 break ;
             case  5 :
                 System.out.println( "你已退出系统!" );
                 System.exit( 0 );
                 
                 break ;
     
             default :
                 System.out.println( "输入错误,请重新输入!!!" );
                 break ;
             }
         }   
     }
     private  static  void  printMenu() {
         System.out.println( "======主菜单======" );
         System.out.println( "1、添加联系人" );
         System.out.println( "2、修改联系人" );
         System.out.println( "3、删除联系人" );
         System.out.println( "4、查看所有联系人" );
         System.out.println( "5、退出系统" );
         System.out.println( "================" );
     }
}

  

到现在我们剩下的工作就是创建一个Operate类来实现该上述接口以完成其具体的功能,但在写的过程中我们注意到喝多代码一直重复着,比如讲一个Document的对象写入本地的xml文档,不管是添加联系人操作还是删除或者修改联系人的操作,这个时候为了提高代码的复用性,我们可以创建以XMLUtil工具类来简化代码,如下:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
package  com.gqx.Test;
import  java.io.FileNotFoundException;
import  java.io.FileOutputStream;
import  java.io.OutputStream;
import  javax.management.RuntimeErrorException;
import  org.dom4j.Document;
import  org.dom4j.DocumentException;
import  org.dom4j.io.OutputFormat;
import  org.dom4j.io.SAXReader;
import  org.dom4j.io.XMLWriter;
/*
  * xml操作的工具类
  */
public  class  XMLUtil {
     //写出一个xml文件
     public  static  void  write2xml(Document doc)  throws  Exception{
         OutputStream out= new  FileOutputStream( "e:/contact.xml" );
         OutputFormat format=OutputFormat.createPrettyPrint();
         format.setEncoding( "utf-8" );
         XMLWriter writer= new  XMLWriter(out,format);
         writer.write(doc);
         writer.close();
     }
     
     //读取本地xml文件的方法
     public  static  Document getDocument(){
         Document doc;
         try  {
             doc =  new  SAXReader().read( "e:/contact.xml" );
             return  doc;
         catch  (DocumentException e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
             throw  new  RuntimeException(e);
         }
         
     }
     
}

  

完成这个操作后,这个时候可以来完成具体的核心操作了

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package  com.gqx.Test;
import  java.io.File;
import  java.io.FileNotFoundException;
import  java.io.FileOutputStream;
import  java.io.OutputStream;
import  java.io.UnsupportedEncodingException;
import  java.util.ArrayList;
import  java.util.List;
import  org.dom4j.Document;
import  org.dom4j.DocumentException;
import  org.dom4j.DocumentHelper;
import  org.dom4j.Element;
import  org.dom4j.Node;
import  org.dom4j.io.OutputFormat;
import  org.dom4j.io.SAXReader;
import  org.dom4j.io.XMLWriter;
public  class  Operator  implements  ContactOperate {
     @Override
     public  void  addContact(Contact contact)  throws  Exception {
         // TODO Auto-generated method stub
         /**
          * 添加联系人,把contact保存到xml文档中
          */
         File file= new  File( "e:/contact.xml" );
         Document doc= null ;
         Element rootElem= null ;
         if  (file.exists()) {
             doc= new  SAXReader().read(file);
             rootElem=doc.getRootElement();
         } else  {
             //如果没有xml文件,创建xml文件
             doc=DocumentHelper.createDocument();
             rootElem=doc.addElement( "contactList" );
         }
     
         //添加contact标签
         Element contactElem=rootElem.addElement( "contact" );
         contactElem.addAttribute( "id" , contact.getId());
         contactElem.addElement( "name" ).setText(contact.getName());
         contactElem.addElement( "sex" ).setText(contact.getSex());
         contactElem.addElement( "age" ).setText(contact.getAge());
         contactElem.addElement( "phone" ).setText(contact.getPhone());
         contactElem.addElement( "email" ).setText(contact.getEmail());
         contactElem.addElement( "qq" ).setText(contact.getQq());
         /**
          * 代码中多处用到将document对象写入xml文档中,
          * 此时可以加强代码的复用性,写一个xml的工具类,
          * 其中一个方法便是将document转化为xml的静态方法
          */
         XMLUtil.write2xml(doc);
     }
     @Override
     public  void  ModifyContact(Contact contact)  throws  Exception {
         // TODO Auto-generated method stub
         //根据xpath快速找到其属性id为xx的contact
         //先读取xml文件
         Document doc= new  SAXReader().read( "e:/contact.xml" );
         //根据xpath快熟找到该节点
         Element contactNode=(Element) doc.selectSingleNode( "//contact[@id='" +contact.getId()+ "']" );
         //根据标签该文本
         contactNode.element( "name" ).setText(contact.getName());
         contactNode.element( "age" ).setText(contact.getAge());
         contactNode.element( "email" ).setText(contact.getEmail());
         contactNode.element( "phone" ).setText(contact.getPhone());
         contactNode.element( "sex" ).setText(contact.getSex());
         XMLUtil.write2xml(doc);
     }
     @Override
     public  void  removeContact(String id)  throws  Exception {
         // TODO Auto-generated method stub
         //先读取xml文件
         Document doc=XMLUtil.getDocument();
         //根据xpath快熟找到该节点
         Element contactNode=(Element) doc.selectSingleNode( "//contact[@id='" +id+ "']" );
         //删除节点
         contactNode.detach();
         XMLUtil.write2xml(doc);
     }
     @Override
     public  List<Contact> checkContacts() {
         // TODO Auto-generated method stub
         Document doc=XMLUtil.getDocument();
         //创建list集合
         List<Contact> list =  new  ArrayList<Contact>();
         List<Element> conList=(List<Element>) doc.selectNodes( "//contact" );
         for  (Element element : conList) {
             Contact contact= new  Contact();
             contact.setId(element.attributeValue( "id" ));
             contact.setAge(element.elementText( "age" ));
             contact.setEmail(element.elementText( "email" ));
             contact.setName(element.elementText( "name" ));
             contact.setPhone(element.elementText( "phone" ));
             contact.setQq(element.elementText( "qq" ));
             contact.setSex(element.elementText( "sex" ));
             list.add(contact);
         }
         return  list;
     }
}

  

注意:有时候在调试以上各种方法的时候,我们可以创建一个调试类,来对每一个具体的操作来调试,可以分别对接口中的每一个方法测试。这样方便发现其中过程是否发生了错误:如

复制代码
package com.gqx.Test;
import java.util.List;
import org.junit.Before;
public class Test {

Operator operator=null;
    
    //初始化这个对象的实例
    @Before
    public void init(){
         operator=new Operator();
    }
    @org.junit.Test
    public void AddContact() throws Exception{
        Contact contact=new  Contact();
        contact.setId("002");
        contact.setAge("21");
        contact.setEmail("454444@qq.com");
        contact.setName("gqxing");
        contact.setPhone("13455555");
        contact.setQq("235346662");
        contact.setSex("男");
        
        operator.addContact(contact);
    }
    
    @org.junit.Test
    public void UpdateContact() throws Exception{
        Contact contact=new  Contact();
        contact.setId("003");
        contact.setAge("0");
        contact.setEmail("0000000@qq.com");
        contact.setName("test");
        contact.setPhone("0-00000000000");
        contact.setQq("000000000000");
        contact.setSex("男");
        
        operator.ModifyContact(contact);
    }
    
    @org.junit.Test
    public void  removeContact() throws Exception{
        operator.removeContact("003");
    }
    @org.junit.Test
    public void  allContact() throws Exception{
        List<Contact> contacts= operator.checkContacts();
        for (Contact contact : contacts) {
            System.out.println(contact);
        }
    }
}
复制代码

  写在最后:实现多功能的操作,可以通过接口或者抽象类去理清其中的关系,避免代码臃肿和杂乱,还有junit是一个很好的测试类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值