天天看點

Javaweb學習筆記——(六)——————xml中jaxp兩種解析方式和dom4j運用

1.xml的scheam限制

 dtd的文法:<!ElEMENT 元素名稱 限制>

 **schema符合xml的文法,xml語句

 **一個xml中可以有多個schema,多個schema使用名稱空間區分(類似于Java的包名)

 **dtd裡面有PADATA類型,但是在schema裡面可以支援更多的資料類型

 ***比如 年齡 隻能是整數,在schema可以直接定義一個整數類型

 

 *** schema文法更加複雜,schema還不能替代dtd



2.schema的快速入門

 *建立一個schema檔案

 **根節點:<schema>

 *步驟

 (1)看xml中有多少個元素

 <element>



 **在schema檔案裡面

 **屬性
 xmlns="http://www.w3.org/2001/XMLSchema" 

 -表示目前xml檔案是一個限制檔案

 targetNamespace="http://www.example.org/1"

 -使用schema限制檔案,直接通過這個位址引入限制檔案 

 elementFormDefault="qualified"



 步驟

 (1)看xml中有多少個元素

 <element>

 (2)看簡單元素和複雜元素

 *如果複雜元素

 <complexType>

 <sequence>

 子元素
 

 </sequence>

 </complexType>



 (3)如果簡單元素,寫在複雜元素的

 <element name="person">

 <complexType>

 <sequence>

 <element name="name" type="string"></element>

 <element name="age" type="int"></element>

 </sequence>

 </complexType>

 </element>



 (4)在被限制檔案裡面引入限制檔案

 <person xmlns:xsi="http://www.w3.org/2001/XMLSchema"

 xmlns="http://www.example.org/1"

 xsi:schemaLocation="http://www.example.org/1 1.xsd">



 **xmlns:xsi="http://www.w3.org/2001/XMLSchema"

 --表示xml是一個被限制檔案



 **xmlns="http://www.example.org/1"

 --是限制文檔裡面 targetNamespace

 **xsi:schemaLocation="http://www.example.org/1 1.xsd"

 --targetNamespace 空格 限制文檔的位址路徑



 *<Sequance>:表示元素的出現的順序

 <all>:元素隻能出現一次

 <choice>:元素隻能出現其中的一個

 maxOccurs="unbounded":表示元素的出現的次數

 <any></any>:表示任意元素



 *可以限制屬性

 *寫在複雜元素裡面

 ***寫在 </complexType>之前

 --

 <attribute name="id1" type="int" use="required"></attribute>

 -name:屬性名稱

 -type:屬性類型 int string

 -use:屬性是否必須出現required



 *複雜的schema限制

 <company xmlns = "http://www.w3.org/2001/XMLSchema"

 xmlns:dept="http://www.example.org/department"

 xmlns:xsi="http://www.w3.org/2001/XMLScema-instance"

 xsi:schemaLocation="http://www.example.org/company company.xsd http://www.example.org/departent department.xsd"

 >



 *引入多個schema檔案,可以給每個起一個别名



 <employee age="30">

 部門名稱

 <dept:name>100</dept:name>

 *想要引入部門的限制檔案裡面的name,使用部門的别名 detp:元素名稱

 員工名稱

 <name>王曉曉</name>

 </employee>



3.sax解析的原理

 *解析xml有兩種技術 dom和sax



 *根據xml中的層級結構在記憶體中配置設定一個樹形結構

 **把xml中标簽,樹形,文本封裝成對象



 *sax方式:事件驅動,邊讀邊解析

 *在javax.xml.parsers包裡面

 ** SAXParser

 此類的執行個體可以從 SAXParserFactory.newSAXParser() 方法獲得

 -parse(File f, DefaultHandler dh)

 *兩個參數

 **第一參數:xml的路徑

 *事件處理器

 ** SAXParserFactory 

 執行個體 newInstance() 方法得到

 *畫圖分析一下sax執行過程

 *當解析到開始标簽的時候,自動執行startElement方法

 *當解析到文本的時候,自動執行characters方法

 *當解析到結束标簽的時候,自動執行endElement方法



4.使用jaxp的sax方式解析xml

 *sax方式不能實作增删改查操作,隻能做查詢操作

 **列印出整個文檔

 ***回寫parse方法,第一個參數xml路徑,第二個參數 事件處理器

 ***建立一個類,繼承事件處理器的類

 ***重寫裡面的三個方法



 *擷取到所有的name元素的值

 **定義一個成員變量 flag = false

 **判斷開始方法是否是name元素,如果是name元素,把flag值設定為true

 **如果flag值為true,才characters方法裡面列印内容

 **當執行到結束方法的時候吧flag值設定成false



 *擷取到第一個name元素的值

 **定義一個成員變量 index = 1

 **在結束方法時候,将 index++

 **想要列印出第一個name元素的值,

 -在characters方法裡面判斷

 --判斷flag=true 并且 index == 1,再列印内容



5.使用dom4j解析xml

 *dom4j,是一個組織,針對xml解析,提供解析器 dom4j



 *dom4j不是javase的一部分,想要使用第一步需要怎麼做?

 ***導入dom4j提供jar包

 --建立一個檔案夾lib

 --複制jar包到lib下面

 --右擊jar包,build path——add to buildpath

 --看到jar包,變成奶瓶樣子,表示導入成功



 *得到document

 SAXReader reader = new SAXReader();

 Document document = reader.read(url);

 *document的父接口是Node

 *如果在document裡面找不到想要的方法,到Node裡面去找



 *document裡面的方法:getRootRlement():擷取根節點 傳回的是Element



 *Element也是一個接口,父接口是Node

 -Element和Node裡面的方法

 ** getParent():擷取父節點

 ** addElement:添加标簽





 * elemnt(qname)   

 **表示擷取标簽下面的第一個子标簽

 **qname:标簽的名稱

 * elements(qname)

 **擷取标簽下面是這個名稱的所有的子标簽(一層)

 **qname:标簽名稱

 *elements()

 **擷取标簽下面的所有的一層子标簽





6.使用dom4j查詢xml

 *解析是從上到下來解析的

 *查詢所有name元素裡面的值

 /*

 1.建立解析器

 2.得到document

 3.得到根節點
 getRootElenment() 傳回Element

 4.得到所有的p1标簽

 *element("p1") 傳回list集合

 *周遊list得到每一個p1

 5.得到name

 *在p1下面執行 element("name")方法 傳回Element

 6.得到name裡面的值

 *getText()得到裡面的值

 */



 *查詢第一個name元素的值

 /*

  * 1.建立解析器

  * 2.得到document

  * 3.得到根節點

  * 

  * 4.得到第一個p1元素

  
 **element("p1")方法 傳回Element

  * 5.得到p1下面的name

  
 **element("name")方法 傳回Element

  * 6.得到name裡面的值

  
 **getText()方法

  */



 *擷取第二個name元素的值

 /*

  * 1.建立解析器

  * 2.得到document

  * 3.得到根節點

  * 

  * 4.得到第二個p1

  
 **傳回list集合

  * 5.得到p1下面的name

  
 **使用list下标得到get方法,集合的下标從0開始,想要得到第二個值,下标寫1

  * 6.得到name裡面的值

  
 **getText方法

  */



7.使用dom4j實作添加操作

 *在第一個p1标簽末尾添加一個元素 <sex>nan</sex>

 *步驟:

 /*

  * 1.建立解析器

  * 2.得到document

  * 3.得到根節點

  * 

  * 4.擷取到第一個p1

  
 *使用element方法

  * 5.在p1下面添加元素

  
 *在p1上面直接使用addElement("标簽名稱")方法 傳回一個Element

  * 6.在添加完成之後的元素下面添加文本

  
 在sex上直接使用 setText("文本内容");方法

  * 

  * 7.回寫xml

  
 *格式化 OutputFormat,使用 createPrettyPrint方法,表示一個漂亮的格式

  
 *使用類XMLWriter 直接new這個類,傳遞這個兩個參數

  
 ***第一個參數是xml檔案路徑 new FileOutputStream("路徑");

  
 ***第二個參數是格式化類的值

  */

8.使用dom4j在特定的位置添加一個元素

 *在第一個p1下面的age标簽之前添加一個 <school>JJU</school>

 *步驟

 /*

  * 1.建立解析器

  * 2.得到document

  * 3.得到根節點

  * 

  * 4.獲得到第一個p1

  * 

  * 5.擷取p1下面的所有的元素

  * 
 **elements()方法 傳回 list集合

  * 
 **使用list裡面的方法,在list裡面添加元素

  * 
 **建立元素,在元素下面建立文本

  
 -使用createElement(QName qname);建立标簽

  
 -把文本添加到标簽下面,使用 setText("文本内容")方法



  * 
 ***add(int index, E element)

  * 
 -第一個參數是位置下标,從0開始

  * 
 -第二個參數是要添加的元素

  * 

  * 6.回寫xml

  */



 **可以對得到document的操作和回寫xml的操作,封裝成方法

 **也可以吧傳遞的檔案路徑,封裝成一個常量

 ***好處:可以提高開發速度,可以提高代碼的可維護性

 -比如想要修改檔案路徑(名稱),這個時候隻需要修改常量的值就可以了,其他代碼不需要改變



9.使用dom4j實作修改節點的操作

 *修改第一個p1下面的age元素的值 <age>30</age>

 *步驟

 /*

  * 1.得到document

  * 2.得到根節點,然後第一個p1元素.

  * 3.得到p1下面的age

  
 element("")方法

  * 4.修改值是30

  
 *使用setText("文本内容")方法

  * 

  * 5.回寫xml

  */



10.使用dom4j來實作删除節點的操作

 *删除第一個p1下面的<school>JJU</school>元素

 *步驟

 /*

  * 1.得到document

  * 2.得到根節點

  * 3.得到第一個p1标簽

  * 4.得到第一個p1下面的school元素

  * 5.删除(使用p1删除school)

  
 *得到school的父節點

  
 -第一種直接得到p1

  
 -使用方法 getParent方法得到

  
 *删除操作

  
 -在p1上面執行remove方法删除節點

  * 

  * 6.回寫xml

  */



11.使用dom4j擷取屬性的需求

 *擷取第一個p1裡面的屬性id的值

 *步驟

 /*

  * 1.得到document

  * 2.得到根節點

  * 3.得到第一個p1元素

  * 4.得到p1裡面的屬性值

  
 -p1.attributeValue("id");

  
 -在p1上面執行這個方法,裡面的參數是屬性名稱

  */

 

 

12.使用dom4j支援xpath的操作

 *可以直接擷取到某個元素



 *第一種形式

 /AAA/DDD/BBB:表示一層一層的,AAA下面的 DDD下面的BBB

 *第二種形式

 //BBB:表示和這個名稱相同,表示隻要名稱是BBB,都得到

 *第三種形式

 /*:所有元素

 *第四種形式

 **
 BBB[1]:表示第一個BBB元素

 **
 BBB[last()]:表示最後一個BBB元素

 *第五種形式

 **
 //BBB[@id]:表示隻要BBB元素上面有id屬性,都得到

 *第六種形式

 **
 //BBB[@id='b1']:表示元素名稱是BBB,在BBB上面有id屬性,并且id的屬性值是b1





13.使用dom4j支援xpath具體操作

 **預設的情況下,dom4j不支援xpath

 **如果想要在dom4j裡面是有xpath

 *第一步需要,引入支援xpath的jar包,使用jaxen-xxxx.jar

 **需要把jar包導入到項目中

 **在dom4j裡面提供了兩個方法,用來支援xpath

 ***
 selectNodes("xpath的表達式")

 -擷取多個節點

 ***selectSingleNode("xpath表達式")

 -擷取一個節點



 **使用xpath實作:查詢xml中所有的name元素的值

 **所有name元素的xpath表示:  //name

 **使用selectNodes("//name");

 **代碼和步驟

 public static void test1(){

 /*

  * 1.得到document

  * 2.直接使用selectNodes("//name")方法的到所有的name元素

  * 

  */

 

 //得到document

 Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);

 

 //直接使用selectNodes("//name")方法的到所有的name元素

 List<Node> list = document.selectNodes("//name");

 

 //周遊list集合

 for(Node node : list){

 //node是每一個name元素

 //得到name元素裡面的值

 String name = node.getText();

 

 System.out.println(name);

 

 }

 }



 **使用xpath實作:擷取第一個p1下面的name的值

 *
 //p1[@id='aaa']/name

 *使用到selectSingleNode("//p1[@id='aaa']/name")

 *步驟和代碼

 public static void test2() {

 /*

  * 1.得到document

  * 2.直接使用selectSingleNode方法實作

  * 
 - xpath://p1[@id='aaa']/name

  */

 

 //得到document

 Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);

 

 //直接使用selectSingleNode方法實作

 Node name = document.selectSingleNode("//p1[@id='aaa']/name");

 

 //擷取name元素下面的值

 String nameStr = name.getText();

 

 System.out.println(nameStr);

 

 }





14.實作簡單的學生管理系統

 **使用xml當做一個資料庫,存儲學生資訊



 **建立一個xml檔案,寫一些學生資訊



 **增加操作

 //增加

 public static void addStu(Student student){

 /*

  * 1.建立解析器

  * 2.得到document

  * 3.得到根節點

  * 4.在根節點上面添加stu标簽

  * 5.在stu标簽上面依次添加id,name,age

  * 6.在id,name,age上面依次添加值

  
 **
 setText()操作

  * 

  * 7.回寫xml

  */

 

 //直接通過工具類擷取document

 Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);

 

 //得到根節點

 Element root = document.getRootElement();

 

 //在根節點上添加stu

 Element stu = root.addElement("stu");

 

 //在根節點上添加id,name,age标簽

 Element id = stu.addElement("id");

 Element name = stu.addElement("name");

 Element age = stu.addElement("age");

 

 //在各個屬性标簽上添加對應的值

 id.setText(student.getId());

 name.setText(student.getName());

 age.setText(student.getAge());

 

 

 //回寫xml

 Dom4jUtils.xmlWriters(Dom4jUtils.PATH, document);

 

 //提示消息

 System.out.println("成功添加"+student.toString()+"的資訊");



 }

 

 **删除操作(根據id删除)

 //删除

 public static void delStu(String id){

 /*

  * 1.通過Dom4jUtil工具類直接擷取document

  * 2.得到根節點

  * 

  * 3.擷取到所有的id

  * 
 使用xpath  //id 傳回list集合

  * 4.周遊list集合

  * 5.判斷集合裡面的id和傳遞的id是否相同

  * 6.如果相同,就把id所在的stu删除(删除父節點,同時該結點下的結點都會被删除)

  * 

  * 7.回寫xml

  */

 

 //擷取document

 Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);

 

 //擷取所有的id

 List<Node> list = document.selectNodes("//id");

 

 //周遊list集合

 for(Node id2 : list){

 //判斷id的值是否和方法中傳過來的id相同

 if (id2.getText().equals(id)) {//相同

 //擷取id2的父節點 stu

 Element stu = id2.getParent();

 //擷取stu的父節點

 Element student = stu.getParent();

 

 //删除stu

 student.remove(stu);

 }

 }

 

 //回寫xml

 Dom4jUtils.xmlWriters(Dom4jUtils.PATH, document);

 

 System.out.println("成功删除 "+id+" 學生的資訊。");

 }



 **查詢操作

 //查詢

 //根據id來查詢學生資訊

 public static Student selectStu(String id) {

 /*

  * 1.根據Dom4jUtil工具直接擷取document

  * 2.擷取到所有的id标簽

  * 3.傳回的list集合,周遊集合

  * 4.得到每一個id節點,

  * 5.擷取每一個id節點的值

  * 6.判斷id的值,和傳遞過來的id值是否相同

  * 7.如果相同,則獲得id的父節點stu

  * 8.獲得stu中的name,age節點中的值



  
 **把這些值封裝到一個對象中,傳回對象

  */

 

 //擷取document

 Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);

 

 //擷取到所有的id标簽

 List<Node> list = document.selectNodes("//id");

 

 //定義nameStr,ageStr

 String nameStr = "";

 String ageStr = "";

 

 //周遊

 for(Node id2 : list){

 //獲得id節點上的值

 String idStr = id2.getText();

 if (idStr.equals(id)) {//相同

 //擷取該節點的父節點stu

 Element stu = id2.getParent();

 

 //擷取結點stu的name節點上的nameStr

 nameStr = stu.element("name").getText();

 

 //擷取結點stu的age節點上的ageStr

 ageStr = stu.element("age").getText();

 

 System.out.println("查詢到一個學生資訊:");

 }

 }

 

 Student student = new Student(id, nameStr, ageStr);

 

 return student;

 }