• 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是一个很好的测试类。

  • 相关阅读:
    c语言的流程控制
    C语言基本用算
    C语言的scanf函数
    C语言一些知识点总结
    C语言程序
    House Robber 分类: leetcode 算法 2015-07-09 20:53 2人阅读 评论(0) 收藏
    [leetcode] Reverse Linked List 分类: leetcode 算法 2015-07-09 18:44 2人阅读 评论(0) 收藏
    合并k个已排序的链表 分类: leetcode 算法 2015-07-09 17:43 3人阅读 评论(0) 收藏
    [leetcode] Reverse Linked List
    Merge k Sorted Lists
  • 原文地址:https://www.cnblogs.com/zhangyubao/p/6973778.html
Copyright © 2020-2023  润新知