XML
1.xml是什麼
xml:(Extensible Markup Language)可擴展標記語言。
由w3c組織提供,2000年開發出1.0版本
xml是一種數據存儲格式,本質上就是一段字符串
2.xml是如何保存數據的
場景:保存中國的省份和城市信息
在XML中, 允許用戶自己定義標籤, 標籤分爲開始標籤和結束標籤, 開始標籤和結束標籤之間又可以嵌套其他的標籤.
正是利用標籤來保存數據, 利用標籤之間的嵌套關係來保存數據之間的層級關係.
3.xml的應用場景
(1)傳輸數據
由於xml本質上是一段字符串, 具有跨平臺的特性, 因此可以在不同系統之間進行數據交換。
比如天氣數據,xml接口:http://flash.weather.com.cn/wmaps/xml/china.xml
(2)用作配置文件
由於xml可以保存有結構的數據, 因此xml常被用來用作應用程序的配置文件。
4.xml文件、xml校驗(瞭解)
我們可以使用瀏覽器對XML進行校驗。
5.xml語法
5.1.文檔聲明
可以用來聲明xml文檔的基本屬性信息, 解析器會根據文檔聲明來決定如何解析這個xml文檔.
注意:
一個xml文檔有且僅有一個文檔聲明.(規範要求)
文檔聲明只能放在xml文檔的第一行, 並且前面不能有任何內容
如果一個xml文檔沒有文檔聲明, 該文檔是一個格式不良好的xml文檔.
<?xml version=”1.0” encoding=”utf-8”?>
其中version用來指定xml文檔所遵循的xml版本, 目前就是1.0, encoding屬性用來通知解析器使用什麼編碼來解析當前xml文檔. 注意, encoding屬性指定的編碼和xml文檔保存時的編碼必須得一致!!!
5.2.元素
一個標籤就是一個元素, 如: <中國></中國>
標籤體:標籤分爲開始標籤和結束標籤, 開始標籤和結束標籤之間的文本。
如:<a>xxxxx</a>
自閉標籤:如果一個元素不包含標籤體也不包含其他元素,那麼可以將開始標籤和結束標籤合併
如:<a></a> ---> <a/>
根標籤:一個xml文檔有且僅有一個根標籤
標籤可以包含子標籤,但一定要合理的嵌套, 不能出現交叉嵌套.
比如:
<a>welcome to <b>www.tarena.com.cn</a></b>
<a>welcome to www.tarena.com.cn</b></a>
<a>welcome to www.tarena.com.cn<b/></a>
<a>welcome to www.tarena<b/>.com.cn</a>
XML元素的命名規範:
區分大小寫, 如: <a>和<A>是兩個不同的標籤
不能以數字或標點符號開頭, 如: <123a>
不能以xml(或Xml、或XML)開頭
不能包含空格
不能包含冒號
5.3.屬性
一個標籤可以有多個屬性,多個屬性之間用空格隔開,屬性值一定要用雙引號(")或單引號(')引起來,例如:
<中國 pyname=”zhongguo” gdp=”70萬億”>
屬性和元素具有相同的命名規範(參考上面)
5.4.註釋 (瞭解)
格式: <!-- 一段註釋 -->
注意:
註釋不能放在文檔聲明的前面
註釋不能交叉嵌套, 如:
<!-- <!-- 註釋內容 註釋內容--> 註釋內容 --> 這是不合理的註釋
5.5.轉義字符 (瞭解)
用其他符號來代替特殊符號
< <
> >
“ "
‘ '
& &
6.xml約束(瞭解)
在xml技術裏,可以編寫一個文檔來約束一個xml文檔的寫法,這稱之爲XML約束。
分爲兩種:DTD和Schema W3C組織提供
7.xml解析
xml兩種解析方式:DOM解析和SAX解析(參見DOM解析圖和SAX解析圖)
解析開發包:jaxp(sun) jdom dom4j
Dom4j解析:
dom4j是一個開源的XML解析包,具有性能優異、功能強大和極其易使用的特點。
案例:操作元素
案例一:查詢第一本書的書名,並輸出到控制檯
1.創建xml文檔:在myEclipse中創建day01項目,在項目中創建book.xml,將dom4j解析用例中的內容拷貝到book.xml中
<?xml version="1.0" encoding="utf-8" ?> <書架> <書> <書名>數據結構</書名> <作者>嚴蔚敏</作者> <售價>29.00元</售價> </書> <書> <書名>高等數學</書名> <作者>同濟大學數學系</作者> <售價>55.00元</售價> </書> </書架> |
2.導包:在項目中創建lib目錄,將javaweb開發軟件中的dom4j-1.6.1.jar複製到lib目錄下,並build path。
3.創建demo1並加入如下代碼
package cn.tedu; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; public class Demo1 { public static void main(String[] args) throws DocumentException { //1.創建解析器 SAXReader reader = new SAXReader(); //2.利用解析器讀取xml文件 Document dom = reader.read("book.xml"); //3.獲取根節點 Element root = dom.getRootElement(); //4.獲取第一本書節點 Element bookEle = root.element("書"); //5.獲取第一個書名節點 Element bookNameEle = bookEle.element("書名"); //6.獲取書名中的內容 String text = bookNameEle.getText(); System.out.println("第一本書的書名爲:"+text); } } |
案例二:查詢第二本書的售價,並輸出到控制檯
package cn.tedu; import java.util.List; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; /** * dom4j操作元素節點 */ public class Demo2 { public static void main(String[] args) throws DocumentException { //2.查詢第二本書的售價,並輸出到控制檯 //1.創建解析器 SAXReader reader = new SAXReader(); //2.利用解析器讀取xml文件 Document dom = reader.read("book.xml"); //3.獲取根節點 Element root = dom.getRootElement(); //4.獲取root下所有節點集合 List<Element> list = root.elements(); //5.獲取第二本書節點 Element bookEle2 = list.get(1); //6.獲取第二本書的售價節點 Element price = bookEle2.element("售價"); //7.獲取售價 String text = price.getText(); System.out.println("第二本書的售價爲:"+text); } } |
爲了方便開發,將案例二中的代碼抽取到一個方法中,可以通過快捷鍵alt+shift+m快速抽取。
發現獲取document部分大量重複,抽取到一個工具類中,代碼如下
/** * 解析xml文件,獲取document對象 * @param xmlPath * @return */ public static Document getDoc(String xmlPath){ try { //1.創建解析器 SAXReader reader = new SAXReader(); //2.利用解析器讀取xml文件 Document dom = reader.read(xmlPath); return dom; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } |
案例三:給第一本書添加一個特價節點(2種方式)
//創建解析器並獲取根節點 Document doc = XMLUtils.getDoc("book.xml"); Element root = doc.getRootElement(); //獲取第一本書 Element bookEle = root.element("書"); /*//方式一 //創建一個遊離的節點 Element priceEle2 = DocumentHelper.createElement("特價"); priceEle2.setText("9.9元"); //將遊離節點掛載到第一本書上 bookEle.add(priceEle2);*/ //方式二 //在第一本書上添加特價子節點 Element priceEle2 = bookEle.addElement("特價"); priceEle2.setText("8.8元"); //將更新的document寫入到xml中,並加入格式輸出器 XMLWriter writer = new XMLWriter( new FileOutputStream(new File("book.xml")),OutputFormat.createPrettyPrint()); writer.write(doc); writer.close(); |
再次發現,輸出到xml的代碼也會大量重複,再次抽取到工具類中
/** * 將更新的document寫入到xml中 * @param doc * @param xmlPath */ public static void write2Xml(Document doc, String xmlPath){ try { //將更新的document寫入到xml中,並加入格式輸出器 XMLWriter writer = new XMLWriter( new FileOutputStream(new File(xmlPath)),OutputFormat.createPrettyPrint()); writer.write(doc); writer.close(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } |
案例四:給第二本書在作者節點前插入一個特價節點
//創建解析器並獲取根節點 Document doc = XMLUtils.getDoc("book.xml"); Element root = doc.getRootElement(); //獲取root下所有節點集合 List<Element> list = root.elements(); //獲取第二個元素 Element bookEle2 = list.get(1); //創建一個遊離節點 Element priceEle2 = DocumentHelper.createElement("特價"); priceEle2.setText("6.6元"); //將遊離節點插入到指定位置 List list2 = bookEle2.elements(); list2.add(1, priceEle2); //將更新的document寫入到xml中 XMLUtils.write2Xml(doc, "book.xml"); System.out.println("執行完畢"); |
案例五:刪除第二本書的特價節點(2種方式)
//創建解析器並獲取根節點 Document doc = XMLUtils.getRootElement("book.xml"); Element root = doc.getDoc(); //獲取root下所有節點集合 List<Element> list = root.elements(); //獲取第二個本書 Element bookEle2 = list.get(1); /*//方法一 //獲取特價節點 Element priceEle2 = bookEle2.element("特價"); //將特價節點從第二本書中刪除 bookEle2.remove(priceEle2);*/ //方法二 //獲取第二本書所有元素 List list2 = bookEle2.elements(); list2.remove(1);
//將更新的document寫入到xml中 XMLUtils.write2Xml(doc, "book.xml"); |
案例六:更新第一本書的特價節點的內容爲19.8元
//創建解析器並獲取根節點 Document doc = XMLUtils.getDoc("book.xml"); doc.getRootElement().element("書").element("特價").setText("19.8元");
//將更新的document寫入到xml中 XMLUtils.write2Xml(doc, "book.xml"); |
操作屬性
案例七:給第一本書添加一個屬性,如:出版社="清華大學出版社"(2種方式)
//創建解析器,讀取xml,獲取根目錄 Document doc = XMLUtils.getDoc("book.xml"); Element root = doc.getRootElement(); //獲取第一本書 Element bookEle = root.element("書"); /*//方法一 //創建一個遊離的屬性 Attribute attr = DocumentHelper.createAttribute(bookEle, "出版社", "清華大學出版社"); //將遊離的屬性掛載到第一本書上 bookEle.add(attr);*/ //方法二 //在第一本書上直接添加屬性 bookEle.addAttribute("版次","1.0"); //將更新的document寫入到xml文檔中 XMLUtils.write2Xml(doc, "book.xml"); |
案例八:在控制檯上打印輸出第一本書的出版社屬性的值,並更新屬性的值爲“人民出版社”(3種方式)
//創建解析器,讀取xml,獲取根目錄 Document doc = XMLUtils.getDoc("book.xml"); Element root = doc.getRootElement(); //獲取第一本書 Element bookEle = root.element("書"); //方式一 //Attribute attr = bookEle.attribute(0); //方式二 Attribute attr = bookEle.attribute("出版社"); attr.setValue("人民出版社"); System.out.println(attr.getName()+":"+attr.getValue()); //方式三 //String value = bookEle.attributeValue("出版社"); //System.out.println(value); //將更新的document寫入到xml文檔中 XMLUtils.write2Xml(doc, "book.xml"); |
案例九:刪除第一本書的出版社屬性(2種方式)
//創建解析器,讀取xml,獲取根目錄 Document doc = XMLUtils.getDoc("book.xml"); Element root = doc.getRootElement(); //獲取第一本書 Element bookEle = root.element("書"); /*//方式一 //獲取第一本書的屬性 Attribute attr = bookEle.attribute("出版社"); //將屬性從第一本書中刪除 bookEle.remove(attr);*/ //方式二 //如果給一個正常值,爲添加,如果給一個null,則爲刪除 bookEle.addAttribute("出版社",null); //將更新的document寫入到xml文檔中 XMLUtils.write2Xml(doc, "book.xml"); |