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