XML可擴展標記語言
1、概念:
XML推出初衷是為了替換HTML,標簽名可以直接定義,不能用數字開頭 不能使用純數字 區分大小寫,後用做配置文件 封裝數據
因為xml具有良好的格式,所以用途非常廣泛,比如持久化存儲數據 數據交換 數據配置
xml和html的區別:
1)html的標簽是固定的,不能擴展。xml的標簽是不固定的,可擴展的。
2)html側重於顯示的信息。xml側重於標識信息的結構。
3)html是不區分大小寫的。xml是區分大小寫的。xml的語法比html更嚴謹。
2、組成部分
文檔聲明:<?xml version="1.0" encoding="utf-8"?>
必須頂行 頂格寫
根標簽:有且僅有一個根標簽
其他標簽:有開始標簽 一定要有結束標簽
標簽屬性:一個標簽可以有多個屬性,每個屬性都有它自己的名稱和取值,例如:<Student name="text">
註解:<!-- --> //Comment註釋對象
標簽裏的內容 egg張三:<name>張三</name>
XML標簽中出現的所有空格和換行,XML解析程序都會當作標簽內容進行處理
3、解析思想
DOM解析思想:Document Object Model 文檔對象模型(dom4j解析)
將文檔一次性 加載進內存 然後將文檔各個組成部分抽取為對象
優點: 能夠對文檔進行增刪改查
缺點:耗內存 適用於PC端
SAX解析思想:基於事件 逐行解析,一次讀取一行,釋放一行(sax解析、pull解析)
優點 :不占內存 適用於移動端
缺點:只能查 不能增刪改
二、dom4j解析
讀取xml文件步驟:
1、導入DOM4J jar包
2、創建解析器對象
SAXReader reader = new SAXReader();
Document doc = reader.read(new FileInputStream("xml文件名.xml"));
3、獲取根標簽對象
Element rootElement = doc.getRootElement();
1) rootElement.node(第幾個節點);//獲取單個節點對象
獲取根標簽下的子節點(不能獲取孫子節點),空白地方也算一個子節點對象
rootElement.nodeIterator();//獲取多個節點對象
2) rootElement.element("標簽名");//獲取第一個子標簽對象
rootElement.elements();//獲取所有的子標簽對象
rootElement.elementIterator();//通過叠代器的方式獲取所有的子標簽對象
4、獲取標簽屬性對象
Element element = rootElement.element("標簽名");
Attribute attribute = element.attribute(第幾個屬性/"屬性名");
attribute.getName();//獲取屬性的鍵
attribute.getValue();//獲取屬性的值
//element.attributes();獲取所有的屬性對象
//element.attributeIterator();通過叠代器的方式獲取所有的屬性對象
//element.attributeValue(第幾個屬性/"屬性名");直接獲取屬性對象的值
5、獲取標簽內文本
List<Element> list = element.elements();
for(Element ele:list){
String text = ele.getText();//獲取文本內容
System.out.println(text);
}
用代碼寫xml文件步驟:
導入DOM4J jar包
//通過文檔幫助類create doc Document doc = DocumentHelper.createDocument(); //添加一個根標簽 Element rootEle = doc.addElement("students"); //添加一個子標簽 Element ele = rootEle.addElement("student"); //給student標簽添加一個屬性 ele.addAttribute("id", "9527"); //給student添加一個名字和學號標簽及內容 Element element1 = ele.addElement("sname"); element1.addText("張三"); Element element2 = ele.addElement("sid"); element2.addText("007"); //把內存中doc 寫到硬盤上 OutputFormat format1 = OutputFormat.createCompactFormat(); OutputFormat format2 = OutputFormat.createPrettyPrint(); //漂亮的格式 // 在開發階段 利於我們調試 可以使用漂亮的格式 // 項目開發好之後上線,我們要調整成緊湊格式 減小xml文件的體積 XMLWriter writer = new XMLWriter(new FileOutputStream("mydoc.xml"), format2); writer.write(doc); writer.close();
用代碼修改xml文件步驟:
//找到你想修改的節點
1)修改屬性的值
attribute.setValue("新屬性值");
2)修改文本
element.setText("新文本");
3)刪除標簽、屬性
element.detach();
attribute.detach();
// 重新寫入到硬盤覆蓋掉原文件
XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("xml文件名.xml"));
xmlWriter.write(doc);
xmlWriter.close();
附:XPath:主要是用於xml快速獲取所需的節點對象
1、導入Dom4j 的jar包 和支持xPath技術的jar包
2、使用xpath方法:
List<Node> list = rootElement.selectNodes("xpath表達式"); 查詢多個節點對象
Node nade = rootElement.selectSingleNode("xpath表達式"); 查詢一個節點對象
3、xpath表達式
/ 絕對路徑 選擇該標簽下子標簽
// 相對路徑 該標簽下所有標簽,表示不分任何層次結構的選擇元素。
* 通配符 表示匹配所有元素
[] 條件 表示選擇什麽條件下的元素
@ 屬性 表示選擇屬性節點,定位一個屬性名
and 關系 表示條件的與關系(等價於&&)
not() 取反
text() 文本 表示選擇文本內容
egg:String path = "//user[@id='2']/name"; //選出所有user標簽中id="2"的user標簽下的name標簽
三、sax解析
sax解析有兩個部分,解析器和事件處理器
解析器就是XMLReader接口,負責讀取XML文檔,和向事件處理器發送事件(也是事件源)
事件處理器ContentHandler接口,負責對發送的事件響應和進行XML文檔處理
為了簡化開發提供了ContentHandler的實現類DefaultHandler類
//事件處理器
public class MyContentHandler extends DefaultHandler{ //文檔解析開始時調用,該方法只會調用一次 @Override public void startDocument() throws SAXException { super.startDocument(); } //標簽開始時調用 @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { //uri:xml文檔的命名空間(用不到) //localName:標簽的名字(用不到) //qName:帶命名空間的標簽的名字(使用標簽名用這個) // attributes:標簽的屬性集 super.startElement(uri, localName, qName, attributes); } //解析標簽的內容的時候調用 @Override public void characters(char[] ch, int start, int length) throws SAXException { //ch:當前讀取到的TextNode(文本節點)的字節數組 //start:字節開始的位置,為0則讀取全部 //length:當前TextNode的長度 super.characters(ch, start, length); } //標簽結束時調用 @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(uri, localName, qName); } //文檔解析結束後調用,該方法只會調用一次 @Override public void endDocument() throws SAXException { super.endDocument(); } }
//解析器
//獲取解析器工廠對象,從而獲取解析器對象
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
//使用指定的DefaultHandler解析指定文件
parser.parse(new File("文件名.xml"), new MyContentHandler());
四、pull解析
Xmlpull比Sax更簡明,而且不需要掃描完整個流
步驟:
//導入kxml2-2.3.0.jar xmlpull_1_1_3_4c.jar第三方jar包
//獲取解析器工廠對象,從而獲取解析器對象 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser parser = factory.newPullParser(); //關聯xml文件 parser.setInput(new FileInputStream("文件名.xml"), "utf-8"); //獲取事件類型 int type = parser.getEventType(); //XmlPullParser.START_DOCUMENT; 文檔開始事件0 //XmlPullParser.END_DOCUMENT; 文檔結束事件1 //XmlPullParser.START_TAG; 開始標簽事件2 //XmlPullParser.END_TAG; 結束標簽事件3 //XmlPullParser.TEXT; 代表文本4 while (type != XmlPullParser.END_DOCUMENT) { String tagName = parser.getName(); switch (type) { case XmlPullParser.START_TAG: if("標簽名".equals(tagName)){ //操作(javabean) }else if("標簽名".equals(tagName)){ //... } break; case XmlPullParser.END_TAG: if("標簽名".equals(tagName)){ //操作(add) } break; } //讓指針跳到下一行,重新給type賦值,不然就會死循環 type = parser.next() } //把內存中的數據序列化到硬盤上去永久保存 //獲取解析器工廠對象,從而獲取序列化器 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlSerializer serializer = factory.newSerializer(); //設置輸出流關聯xml文件 serializer.setOutput(new FileOutputStream("文件名.xml"), "utf-8"); //寫入文檔聲明(文檔開始) serializer.startDocument("utf-8", true);//參數二:文檔是否獨立 //寫入開始根標簽 serializer.startTag(null, "students");//參數1 命名空間一般給null 參數2 標簽名稱 //寫入根標簽的子標簽student開始標簽 serializer.startTag(null, "student"); serializer.attribute(null, "id", "id值");//寫入屬性 //寫入student標簽的子標簽name開始標簽 serializer.startTag(null, "name"); //寫入name標簽內文本 serializer.text("文本內容"); //寫入name結束標簽 serializer.endTag(null, "name"); //同樣方法寫student標簽的子標簽age //寫入student結束標簽 serializer.endTag(null, "student"); //同樣方法寫多個student,一般使用循環 //寫入結束根標簽 serializer.endTag(null, "students"); //文檔結束 serializer.endDocument();
XML可擴展標記語言