• 【常用API】之XML文档解析


    【XML文档】

    数据彼此交互,本地可以使用 序列化文件。
    主要针对本地化操作:应用程序,游戏。
    序列化操作,必须有原始类文件。

    如果数据需要提供互联网共享,
    企业与企业之间进行数据交互。
    那就使用XML文档。


    XML文档,是由 W3C 定义的一套标准规范。
    所有语言,所有平台都兼容识别。
    【xml文档不受平台与语言的限制,跨平台,跨语言】


    XML:可扩展的 标记 语言

    xml是利用一套标记标签进行内容(数据)的定义与描述的。
    <标签 />
    <开始标签>内容</结束标签>

    【定义与使用】:

    xml文档的定义有严格规定:
    1、文档必须是.xml结尾的后缀
    2、文档第一行开始部分,必须是一个声明,
    且声明的前面不能有任何内容。
    <?xml version="1.0" encoding="utf-8" ?>
    3、一个xml文档中,只能有一个最大的根元素
    4、如果标签有属性,属性必须小写,且属性的值必须有双引号
    <user id="555"></user>

    创建XML文档,也需要流对象

    FileInputStream 基础字节输出流(写)

    PrintStream 打印流

    .print(String) 方法,一次性写入

    创建XML实例:

    1、首先创建一个用户实体模型类User,用于生成XML

    package com.xzm.test;
    
    //用户的数据实体模型类
    public class User {
        
        //属性
        private int id;
        private String name;
        private int age;
        
        //属性封装
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        
    }

    2、根据XML文档定义的格式,手动生成XML文档

    package com.xzm.test;
    
    //导入需要的包文件
    import java.util.List;
    import java.io.FileOutputStream;
    import java.io.PrintStream;
    import java.util.ArrayList;
    
    
    public class 生成_XML {
    
        public static void main(String[] args) {
            
            //【生产数据 放入集合中】==========================
            List<User> list = new ArrayList<User>();
            
            //利用循环存入对象
            for(int i=1; i<=5; i++)
            {
                //创建User类对象
                User u = new User();
                
                //设置属性值
                u.setId(1000+i); 
                u.setName("张三"+i);
                u.setAge( (int)Math.round( Math.random()*12+18 ) );//生成随机年龄18-30
            
                //放入集合中
                list.add(u);
            }
            
            //显示内存地址
            System.out.println(list);
            
            
            
            //=========================================================
            //【基于数据list,组合xml内容】
            
            //第一步:
            //    创建一个字符串操作对象,里面是保存xml组合的内容的
            //    由于是单线程应用程序
            //    在组合操作内容的时候,不会产生多余的内存对象
            StringBuilder sb = new StringBuilder();
            
            //第二步:
            //    追加:xml头部声明:
            //    内容中,使用转义,保留双引号本身
            sb.append("<?xml version="1.0" encoding="utf-8" ?>");
            
            //第三步:
            //    追加:最大根元素---开始标签
            sb.append("<table>");        
            
            //遍历集合,组合中间的内容
            for(User u : list)
            {
                //二级标签---开始
                sb.append("<user>");
                
                //三级标签: StringBuilder中,.append方法是可以连续使用的
                sb.append("<id>").append(u.getId()).append("</id>");
                sb.append("<name>").append(u.getName()).append("</name>");
                sb.append("<age>").append(u.getAge()).append("</age>");
                
                //二级标签---结束
                sb.append("</user>");
            }        
            
            //    追加:最大根元素---结束标签
            sb.append("</table>");
            
            
            //预览组合数据
            System.out.println(sb);
            
            
            
            //=======================================================
            //【生成xml】
            try {
                //注意:
                //    由于操作系统是简体中文的,默认系统生成的文件都是ANSI(gb2312),
                //    我们的内容中有特殊字符,但是文档声明为 utf-8
                //    如果直接写文件,字符流是可以的,但是会容易导致:中文乱码。
                //    【打印流:PrintStream】,直接解决编码问题。
                
                //创建基础字节输出流(文件的保存格式是字节)
                //这里不需要File对象,直接指定路径文件名
                //没有指定物理路径:当前项目根目录下
                FileOutputStream fos = new FileOutputStream("table.xml");
            
                //创建 高层 内容 打印流
                //【必须使用三个参数的构造方法实例化】
                //(流对象,是否自动完成true,编码utf-8)
                PrintStream ps = new PrintStream(fos, true, "utf-8");
            
                //调用方法打印
                ps.print(sb);
                
                //关闭
                ps.close();
                fos.close();
                
                //结果
                System.out.println("创建成功!");        
            }
            catch(Exception ex) {
                ex.printStackTrace();
            }
    
        }
    
    }

    解析XMl的方式有两种,一种SAX方式,一种DOM方式

    SAX解析:
    表示的是通过代码,逐行解析,
    会按照层次关系,一个个一次提取递进。
    优点:内存消耗少,每次只有一个信息
    缺陷:必须按照它的顺序进行逐步操作
    必须实现一个类对象,且重写方法去操作

    package com.xzm.test;
    
    import java.io.FileInputStream;
    
    import javax.xml.parsers.SAXParser;
    import javax.xml.parsers.SAXParserFactory;
    
    import org.xml.sax.Attributes;
    import org.xml.sax.SAXException;
    import org.xml.sax.helpers.DefaultHandler;
    
    public class SAX解析_XML {
        public static void main(String[] args) {
            
            try {
                
                //SAX解析方式:
                //    打开文件,按照流的方式,一个一个节点递进的。
                //    节约内存使用,但是会长时间链接文件,不能任意控制。
                
                //第一步:
                //    自定义一个类,继承DefaultHandler类,
                //    重写里面的方法
                //    这些方法都是自动调用的,我们只要实现里面具体的代就可以
                
                //第二步:
                //    得到一个SAX解析工厂
                SAXParserFactory sax = SAXParserFactory.newInstance();
                
                //第三步:
                //    基于工厂,得到解析对象
                SAXParser sp = sax.newSAXParser();
                
                //第四步:
                // 创建基础输入流
                FileInputStream fis = new FileInputStream("table.xml");
                
                //第五步:
                // 调用方法,解析文档
                // 基于输入流操作的,同时提供类对象
                // 读取过程,自动调用类中重写的方法
                sp.parse(fis, new MyHandler());
                
                //关闭
                fis.close();
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }    
    }
    
    //==============================================================
    class MyHandler extends DefaultHandler
    {
        
        //文档开始
        @Override
        public void startDocument() throws SAXException {
            super.startDocument();
            System.out.println("文档开始");
        }
    
        //读取到-开始标签: qName:标签名称
        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
            super.startElement(uri, localName, qName, attributes);
            System.out.println("<"+qName+">");
        }
        
        //标签中的内容
        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            super.characters(ch, start, length);
            
            //标签中的内容,程序会按照一个个字符char,读取出来,
            //保存到数组 ch 中,
            //会记录开始的字符索引,同时记录内容的长度
            //当前方法自动传入
            //把这三个参数 直接给 String类对象
            //String类对象会自动从整个字符串文本中,提取出这一点信息
            String str = new String(ch, start, length);
            System.out.println(str);
        }
        
    
        //读取到-结束标签
        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            super.endElement(uri, localName, qName);
            System.out.println("</"+qName+">");
        }
        
        
        //文档结束
        @Override
        public void endDocument() throws SAXException {
            super.endDocument();
            System.out.println("文档结束");
        }
    }

    DOM解析:
    表示的是 Document 文档解析,
    它可以一次性把整个xml文档的内容提取出来。
    优点:用户可以任意 遍历、提取、操作等等。
    缺陷:内存消耗过大

    package com.xzm.test;
    
    import java.io.File;
    
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.NodeList;
    
    public class DOM解析_XML {
    
        public static void main(String[] args) {
            
            try {
                //DOM解析方式:
                //    通过Dom工厂,一次性把文档信息读取到内存上
                //    减少了IO操作,增加内存使用
                
                //第一步:
                // 得到一个文档构建工厂,调用类中静态方法得到对象的
                DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                
                
                //第二步:
                // 基于工厂,得到一个文档构建对象
                DocumentBuilder db = dbf.newDocumentBuilder();
                
                
                //第三步:
                // 指定数据源文档对象
                File f = new File("table.xml");
                
                
                //第四步:
                // 通过文档对象调用方法,获取数据源所有内容
                Document doc = db.parse(f);
                
                //======================================================
                //此时:doc对象中,已经得到了整个xml中的所有内容            
                //接下来,就是基于doc对象,在里面操作了
                
                //doc读取的文档信息中,有以下三种类型的内容:
                //    声明:<?xml ?>
                //    元素:Element:最大的根元素:<table>
                //    节点:Node:内部的元素:table标签中包括的所有
                
                
                //【得到最大的根元素】
                Element table = doc.getDocumentElement();
                
                //【得到这个根元素的节点名称】
                //String name = table.getNodeName();
                //System.out.println(name);
                
                
                //【第一层:子节点】
                //在根元素中,得到第一层子节点
                //基于根对象,获取所有的子节点
                //【注意:换行也会当作节点】
                NodeList nl = table.getChildNodes();
                //System.out.println( nl.getLength() );
                
                
                //循环遍历每一个二级子节点
                for(int i=0; i<nl.getLength(); i++)
                {
                    //从当前二级节点中,获取第三级节点列表
                    NodeList ns = nl.item(i).getChildNodes();
                    
                    //遍历第三级
                    for(int j=0; j<ns.getLength(); j++)
                    {
                        //获取遍历到第三级节点的信息
                        System.out.print("节点名称:" + ns.item(j).getNodeName());                    
                        System.out.println(",文本内容:" + ns.item(j).getTextContent());
                    }                
                }
                
                
                
                
                
                
                
                
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
    }
  • 相关阅读:
    使用C++11实现线程池的两种方法
    二分查找算法的几种实现
    UNP多线程编程技巧简单总结
    使用带外数据设置 C/S 心跳机制
    无法修正错误,因为您要求某些软件包保持现状
    2012.12-操作系统-吕晓鑫-计算机操作系统综述
    2013.03-多核操作系统-梁荣晓-多核操作系统发展综述
    2011.09-多核操作系统-李彦冬-多核操作系统发展综述
    Simultaneous Multithreading: Maximizing On-Chip Parallelism(精读)
    Simultaneous Multithreading: Maximizing On-Chip Parallelism(泛读)
  • 原文地址:https://www.cnblogs.com/jiarenanhao/p/14147800.html
Copyright © 2020-2023  润新知