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