码迷,mamicode.com
首页 > Windows程序 > 详细

【常用API】之XML文档解析

时间:2020-12-22 11:59:41      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:引号   编码问题   实体   pen   三级   字符串操作   系统   extc   vat   

【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();
        }
    }
    
}

 

【常用API】之XML文档解析

标签:引号   编码问题   实体   pen   三级   字符串操作   系统   extc   vat   

原文地址:https://www.cnblogs.com/jiarenanhao/p/14147800.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!