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;
}