xml基礎知識


關鍵詞:xml、DTD約束、Schema約束、dom解析、sax解析、jaxp解析器、dom4j解析器
一、xml的簡介
1、eXtensible Markup Language:可擴展標記型語言
①標記型語言:HTML是標記型語言,即使用標簽來操作。
②可擴展:
  • HTML里面的標簽是固定,每個標簽都有特定的含義<h1><br/><hr/>
  • 標簽可以自己定義,可以寫中文的標簽<person></person>、<貓></貓>
2、xml用途
①HTML是用於顯示數據,xml也可以顯示數據(不是主要功能)
②xml主要功能,為了儲存數據
3、xml是W3C組織發布的技術,目前有兩個版本1.0、1.1
  目前使用的都是1.0版本(1.1版本不能向下兼容)
二、xml的應用
1、不同的系統之間傳輸數據
2、用來表示生活中有關系的數據
3、經常用在配置文件,如:現在連接數據庫,肯定知道數據庫的用戶名和密碼,數據庫名稱,如果修改數據的信息,不需要修改源代碼,只要修改配置文件就可以了。
三、xml的語法
1、xml的文檔聲明
①創建一個文件 后綴名是 .xml
②如果寫xml,第一步必須要有一個文檔聲明(寫了文檔聲明之后,表示寫xml文件的內容)
  <?xml version="1.0" encoding="gbk"?> 
  • 在“<”和“?”之間、“?”和“>”之間和“xml”之間不能有空格。
  • 文檔聲明必須寫在第一行第一列
  • 屬性:
    • version:xml的版本1.0(使用)1.1
    • encoding:xml編碼gbk utf-8 iso8859-1(不包含中文)
    • standalone:是否需要依賴其他文件yes/no
③xml的中文亂碼問題解決:保存時候和設置打開時的編碼一致,不會出現亂碼
2、定義元素(標簽)
  ①標簽定義
  • 標簽定義有開始必須有結束:<person></person>
  • 標簽沒有內容,可以在標簽內結束:<aa/>
  • 標簽可以嵌套,必須要合理嵌套
    • 合理嵌套:<aa><bb></bb></aa>
    • 不合理嵌套:<aa><bb></aa></bb>,這種方式是錯誤的
  • 一個xml中,只能有一個根標簽,其他標簽都是這個標簽下面的標簽
  • 在xml中把空格和換行都當成內容來解析,
    • 下面這兩段代碼含義是不一樣的
<aa>1111111</aa>
<aa>
    1111111
</aa>
  ②xml中標簽的命名規則(可以用中文)
    • xml代碼區分大小寫,如<p><P>是兩個不同的標簽
    • 不能以數字或“_”(下划線)開頭
    • 不能以xml(或XML、或Xml等)開頭
    • 不能包含空格
    • 名稱中間不能包含冒號(:)。
3、定義屬性
①在xml文檔中,可以為元素定義屬性
  <person id1="aa" id2="bb"></person> 
②屬性定義要求
  • 一個標簽上可以有多個屬性,如:<person id1="aa" id2="bb"></person>
  • 屬性名稱不能相同,如<person id="aa" id="bb"></person>,出現錯誤
  • 屬性名稱和屬性值之間使用=,屬性值使用引號包起來(可以是單引號,也可以雙引號)
  • xml屬性的命名規范和元素的命名規范一致
4、注釋
  寫法:<!-- 注釋信息 -->
  • 注釋不能放到第一行,第一行必須放文檔說明
  • 注釋不能出現在標記中,如非法寫法: <greeting <!--Begin greet-->></greeting> 
  • 字符串“--”不能出現在注釋中,如非法寫法: <!--This is a Example--Hello World--> 
  • 在xml中,不允許注釋以“--->”結尾。
  • 注釋不嵌套
5、特殊字符
  利用轉義字符
特殊符號 預定義實體 特殊符號 預定義實體
& &amp; " &quot;
< &lt; ' &apos
> &gt;    
6、CDATA區
可以解決多個字符都需要轉義的操作 if (a<b && b<c && d>f){}
把這些內容放到CDATA區里面,不需要轉義了
寫法:  <![CDATA[ 內容 ]]> 
如:  <![CDATA[ <b>if (a<b && b<c && d>f){} </b> ]]> 
把特殊字符當做文本內容,而不是標簽
7、PI指令(處理指令)(了解)
可以在xml中設置樣式
寫法:  <?xml-stylesheet type="text/css" href="css的路徑"?> 
設置樣式,只能對英文標簽名稱起作用,對於中文的標簽名稱不起作用的。
8、xml語法總結:
  • 所有xml元素都必須有關閉標簽
  • xml 標簽對大小寫敏感
  • xml 必須正確嵌套順序
  • xml文檔必須有根元素(只有一個)
  • xml 的屬性值需加引號
  • 特殊字符必須轉義 ----CDATA
  • xml 中的空格、回車換行會解析時被保留
四、xml的約束
  約束的作用:
如現在定義一個person的xml文件,只想要這個文件里面保存人的信息,比如name age等,但是如果在xml文件中寫一個標簽<貓>,發現可以正常顯示,因為符合語法規范。但是貓肯定不是人的信息,xml的標簽是自定義的,需要技術來規定xml中只能出現的元素,這個時候需要約束。
xml的約束的技術:DTD約束 和Schema約束。
1、DTD的快速入門
創建一個文件,后綴名為“.dtd”
步驟:
(1) 看xml中有幾個元素,有幾個元素,在dtd文件中寫幾個<!ELEMENT>
(2) 判斷元素是簡單元素還是復雜元素
-復雜元素:有子元素的元素
  <!ELEMENT 元素名稱 (子元素)> 
-簡單元素:沒有子元素
  <!ELEMENT 元素名稱 (#PCDATA)> 
(3)需要在xml文件中引入dtd文件三種引入方式:
①引入外部的dtd文件
  <!DOCTYPE 根元素名稱 SYSTEM “dtd文件的路徑”> 
②使用內部的dtd文件
<!DOCTYPE 書架 [
     <!ELEMENT 書架 (書+)>
     <!ELEMENT 書 (書名,作者,售價)>
     <!ELEMENT 書名 (#PCDATA)>
     <!ELEMENT 作者 (#PCDATA)>
     <!ELEMENT 售價 (#PCDATA)>
 ]>
③使用外部的dtd文件(網絡上的dtd文件)
  <!DOCTYPE 根元素名稱 PUBLIC "DTD名稱" “DTD文件的URL”> 
在框架struts2使用配置文件 使用外部的dtd文件
示例:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE 書架 SYSTEM "book.dtd">
<書架>
    <>
        <書名>Java就業培訓教程</書名>
        <作者>張孝祥</作者>
        <售價>58.00元</售價>
        <!--如果添加dtd中無添加的元素,就會報錯,即為約束-->
    </>
    <>
        <書名>EJB3.0入門經典</書名>
        <作者>黎活明</作者>
        <售價>39.00元</售價>
    </>
</書架>
book.dtd :
<!ELEMENT 書架 (書+)>
    <!ELEMENT 書 (書名,作者,售價)>
        <!ELEMENT 書名 (#PCDATA)>
        <!ELEMENT 作者 (#PCDATA)>
        <!ELEMENT 售價 (#PCDATA)>
2、使用dtd定義元素
  語法:  <!ELEMENT 元素名 約束> 
    -簡單元素:沒有子元素
      <!ELEMENT 元素名稱 (#PCDATA)> 
    • (#PCDATA):約束元素為字符串類型
    • EMPTY:約束元素為空
    • ANY:任意
    -復雜元素:有子元素的元素
      <!ELEMENT 元素名稱 (子元素)> 
表示子元素出現的次數
    • +:表示一次或者多次
    • ?:表示零次或者一次
    • *:表示零次或者多次
子元素直接使用逗號“,”進行隔開,表示元素出現的順序
子元素直接使用“|”隔開,表示元素只能出現其中的任意一個
括號“()”,用於給元素進行分組
  示例:
    <!ELEMENT person (name+,age?,sex*,school)> 
3、使用dtd定義屬性
  ①語法:  <!ATTLIST 元素名稱 屬性名稱 屬性類型 屬性的約束 > 
  ②屬性類型:
  -CDATA:字符串
    <!ATTLIST birthday ID1 CDATA #REQUIRED > 
  -枚舉:表示只能在一定范圍內出現值,但是只能每次出現其中的一個
  如:紅綠燈效果、(aa|bb|cc)
    <!ATTLIST age ID2 (AA|BB|CC) #REQUIRED > 
  -ID:值只能是字母或下划線開頭
    <!ATTLIST name ID3 ID #REQUIRED> 
  ③屬性的約束
-#REQUIRED:屬性必須存在
-#IMPLIED:屬性可有可無
-#FIXED:表示一個固定值 ,如#FIXED "AAA"
  屬性的值必須是設置的這個固定值
    <!ATTLIST sex ID4 CDATA #FIXED "AAA"> 
-直接值
不寫屬性,使用直接值
寫了屬性,使用設置那個值
    <!ATTLIST school ID5 CDATA “WWW”> 
4、實體的定義
  語法:  <!ENTITY 實體名稱 “實體的值”> 
    <!ENTITY TEST "HAHAHA">
    使用實體 &實體名稱; 比如: &TEST;
  注意:定義實體需要寫在內部dtd里面,如果寫在外部的dtd里面,在某些瀏覽器下,內容無法顯示。
五、xml解析的簡介
1、xml是標記型文檔
2、js使用dom解析標記型文檔?
  根據html的層級結構,在內存中分配一個樹形結構,把html的標簽,樹形結構,把html的標簽,屬性和文本都封裝成對象
  document對象、element對象、屬性對象、文本對象、Node節點對象
3、xml的解析方式(技術):dom和sax
①dom解析和sax解析區別:
dom方式解析:根據xml的層級結構在內存中分配一個樹形結構,把xml的標簽,屬性和文本都封裝成對象
缺點:如果文件過大,造成內存溢出
優點:很方便實現增刪改操作
 
  sax方式解析:采用事件驅動,邊讀邊解析,
從上到下,一行一行的解析,解析到某一個對象,把對象名稱返回
缺點:不能實現增刪改操作
優點:如果文件過大不會造成內存溢出,實現查詢操作
②xml解析器:不同的公司和組織提供了針對dom和sax方式的解析器,通過api方式提供
  • sun公司提供了針對dom和sax解析器 jaxp
  • dom4j組織,針對dom和sax解析器 dom4j(實際開發中使用)
  • jdom組織,針對dom和sax解析器 jdom
4、jaxp的api的查看
  jaxp是javase中的一部分,jaxp解析器在jdk的javax.xml.parsers包里面
  四個類:分別是針對dom和sax解析使用的類
  ①dom:
    DocumentBuilder:解析器類
      -抽象類,不能new
        此類的實例可以從DocumentBuilderFactory.newDocumentBuilder() 方法獲取
      -一個方法,可以解析xml parse(“xml”路徑) 返回是Document整個文檔
      -返回的document是一個接口,父節點是Node,如果在document里面找不到想要的方法,到Node里面去找
      -在document里面方法
getElementsByTagName(String tagname)
--這個方法可以得到標簽
--返回集合NodeList
createElement(String tagName)
  --創建標簽
createTextNode(String data)
  --創建文本
appendChild(Node newChild)
  --把文本添加到標簽下面
removeChild(Node oldChild)
  --刪除節點
getParentNode()
  --獲取父節點
getTextContent()
  --得到標簽里面的內容
 
    DocumentBuilderFactory:解析器工廠
  ②sax:
SAXParser: 解析器類
SAXParserFactory:解析器工廠
5、使用jaxp實現增刪改查操作
①、使用jaxp實現查詢操作
查詢xml中所有的name元素的值
步驟:
1、創建解析器工廠
  DocumentBuilderFactory.newInstance();
2、根據解析器工廠創建解析器
  builderFactory.newDocumentBuilder();
3、解析xml返回document
  Document document = builder.parse(uri);
4、得到所有的name元素
  使用document.getElementsByTagName("name");
5、返回集合,遍歷集合,得到每一個name元素
-遍歷 getLength() item()
-得到元素里面值 使用getTextContent()
 
查詢xml中第一個name元素的值
步驟:
1、創建解析器工廠
2、根據解析器工廠創建解析器
3、解析xml返回document
4、得到所有的name元素
5、使用返回集合,里面方法item,下標獲取具體的元素
Nodelist.item(下標):集合下標從0開始
6、得到具體的值,使用getTextContent方法
  ②使用jaxp添加節點
  在第一個p1下面(末尾)添加<sex>nv</sex>
步驟:
1、創建解析器工廠
2、根據解析器工廠創建解析器
3、解析xml返回document
4、得到第一個p1(得到所有p1,使用item方法下標得到)
5、創建sex標簽createElementNode
6、串及文本createTextNode
7、把文本添加到sex下面appendChild
8、把sex添加到第一個p1下面
9、回寫xml
  ③使用jaxp修改節點
  修改第一p1下面的sex內容是男
步驟:
1、創建解析器工廠
2、根據解析器工廠創建解析器
3、解析xml返回document
4、得到sex item方法
5、修改sex里面的值setTextContent方法
6、回寫xml
④使用jaxp刪除節點
刪除<sex>男</sex>節點
步驟:
1、創建解析器工廠
2、根據解析器工廠創建解析器
3、解析xml返回document
4、獲取sex元素
5、獲取sex的父節點,使用getParentNode方法
6、刪除,使用父節點刪除removeChild方法
7、回寫xml
⑤使用jaxp遍歷節點
遍歷節點,把xml中的所有元素名稱打印出來
步驟:
1、創建解析器工廠
2、根據解析器工廠創建解析器
3、解析xml返回document
===使用遞歸實現======
4、得到根節點
5、得到根節點子節點
6、得到根節點子節點的子節點
遍歷方法:
private static void list1(Node node) {
    //判斷元素類型時候才打印
    if (node.getNodeType() == Node.ELEMENT_NODE){
        System.out.println(node.getNodeName());
    }
    //得到一層子節點
    NodeList list = node.getChildNodes();
    //遍歷list
    for(int i=0; i<list.getLength();i++){
        //繼續得到node1的子節點
        Node node1 = list.item(i);
        list1(node1);
    }
}
 實例:
  xml文檔:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><person>
    <p1>
        <name>zhangsan</name>
        <age>20</age>
        <sex></sex>
    </p1>
    <p1>
        <name>lisi</name>
        <age>30</age>
    </p1>
</person>}
  1 package jaxptest;
  2 import org.w3c.dom.*;
  3 import javax.xml.parsers.DocumentBuilder;
  4 import javax.xml.parsers.DocumentBuilderFactory;
  5 import javax.xml.transform.Transformer;
  6 import javax.xml.transform.TransformerFactory;
  7 import javax.xml.transform.dom.DOMSource;
  8 import javax.xml.transform.stream.StreamResult;
  9 
 10 public class TestJaxp {
 11     public static void main(String[] args) throws Exception{
 12         String uri = "src/person.xml";
 13 //        selectAll(uri);
 14 //        selectSin(uri);
 15 //        addSex(uri);
 16 //        modifySex(uri);
 17 //        delSex(uri);
 18         listElement(uri);
 19     }
 20     //解析dom方法解析xml文檔方法
 21     private static Document jaxpParseXml(String uri) throws Exception {
 22         //創建解析器工廠
 23         DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
 24         //創建解析器
 25         DocumentBuilder builder = builderFactory.newDocumentBuilder();
 26         //解析xml返回document
 27         Document document = builder.parse(uri);
 28         return document;
 29     }
 30     //回寫xml方法
 31     private static void writeBack(Document document,String uri) throws Exception{
 32         TransformerFactory transformerFactory = TransformerFactory.newInstance();
 33         Transformer transformer = transformerFactory.newTransformer();
 34         transformer.transform(new DOMSource(document),new StreamResult(uri));
 35     }
 36     //查詢所有name元素的值
 37     public static void selectAll(String uri) throws Exception {
 38         //查詢所有name元素的值
 39         /*
 40         * 1、創建解析器工廠
 41         * 2、根據解析器工廠創建解析器
 42         * 3、解析xml返回document
 43         * 4、得到所有的name元素
 44         * 5、返回集合,遍歷集合,得到每一個name元素
 45         * */
 46         Document document = jaxpParseXml(uri);
 47         //得到name元素
 48         NodeList list = document.getElementsByTagName("name");
 49         //遍歷集合
 50         for(int i=0;i<list.getLength();i++) {
 51             Node name1 = list.item(i);
 52             //得到name1元素里面的值
 53             String s = name1.getTextContent();
 54             System.out.println(s);
 55         }
 56     }
 57     //查詢xml中第一個name元素的值
 58     public static void selectSin(String uri) throws Exception{
 59         /*
 60         * 1、創建解析器工廠
 61         * 2、根據解析器工廠創建解析器
 62         * 3、解析xml返回document
 63         * 4、得到所有的name元素
 64         * 5、使用返回集合,里面方法item,下標獲取具體的元素
 65         * 6、得到具體的值,使用getTextContent方法
 66         * */
 67         Document document = jaxpParseXml(uri);
 68         NodeList list = document.getElementsByTagName("name");
 69         Node name1 = list.item(0);
 70         String s1 = name1.getTextContent();
 71         System.out.println(s1);
 72     }
 73     //在第一個p1下面(末尾)添加<sex>nv</sex>
 74     public static void addSex(String uri) throws Exception {
 75         /*
 76         * 1、創建解析器工廠
 77         * 2、根據解析器工廠創建解析器
 78         * 3、解析xml返回document
 79         * 4、得到第一個p1(得到所有p1,使用item方法下標得到)
 80         * 5、創建sex標簽createElementNode
 81         * 6、串及文本createTextNode
 82         * 7、把文本添加到sex下面appendChild
 83         * 8、把sex添加到第一個p1下面
 84         * 9、回寫xml
 85         * */
 86         Document document = jaxpParseXml(uri);
 87         NodeList list = document.getElementsByTagName("p1");
 88         Node p1 = list.item(0);
 89         Element sex1 = document.createElement("sex");
 90         Text text = document.createTextNode("女");
 91         sex1.appendChild(text);
 92         p1.appendChild(sex1);
 93         writeBack(document,uri);
 94     }
 95     //修改第一p1下面的sex內容是男
 96     public static void modifySex(String uri) throws Exception{
 97         /*
 98         * 1、創建解析器工廠
 99         * 2、根據解析器工廠創建解析器
100         * 3、解析xml返回document
101         * 4、得到sex item方法
102         * 5、修改sex里面的值setTextContent方法
103         * 6、回寫xml
104         * */
105         Document document = jaxpParseXml(uri);
106         Node sex1 = document.getElementsByTagName("sex").item(0);
107         sex1.setTextContent("男");
108         writeBack(document,uri);
109     }
110     //刪除<sex>男</sex>節點
111     public static void delSex(String uri) throws Exception{
112         /*
113         * 1、創建解析器工廠
114         * 2、根據解析器工廠創建解析器
115         * 3、解析xml返回document
116         * 4、獲取sex元素
117         * 5、獲取sex的父節點,使用getParentNode方法
118         * 6、刪除,使用父節點刪除removeChild方法
119         * 7、回寫xml
120         * */
121         Document document = jaxpParseXml(uri);
122         Node sex1 = document.getElementsByTagName("sex").item(0);
123         Node p1 = sex1.getParentNode();
124         p1.removeChild(sex1);
125         writeBack(document,uri);
126     }
127     //遍歷節點,把xml中的所有元素名稱打印出來
128     public static void listElement(String uri) throws Exception {
129          /*
130         * 1、創建解析器工廠
131         * 2、根據解析器工廠創建解析器
132         * 3、解析xml返回document
133         * ===使用遞歸實現======
134         * 4、得到根節點
135         * 5、得到根節點子節點
136         * 6、得到根節點子節點的子節點
137         * */
138         Document document = jaxpParseXml(uri);
139         //編寫一個方法實現遍歷操作
140         list1(document);
141     }
142     private static void list1(Node node) {
143         //判斷元素類型時候才打印
144         if (node.getNodeType() == Node.ELEMENT_NODE){
145             System.out.println(node.getNodeName());
146         }
147         //得到一層子節點
148         NodeList list = node.getChildNodes();
149         //遍歷list
150         for(int i=0; i<list.getLength();i++){
151             //繼續得到node1的子節點
152             Node node1 = list.item(i);
153             list1(node1);
154         }
155     }
六、Schema約束
(一)schema介紹
dtd語法:<!ELEMENT 元素名稱 約束>
schema符號xml的語法,xml語句
一個xml中可以有多個schema,多個schema使用名稱空間區分(類似於Java包名)
dtd里面有PCDATA類型,但是在schema里面可以支持更多的數據類型
比如年齡只能是整數,在schema中可以直接定義一個整數類型
schema語法更加復雜,schema目前不能替代dtd
(二)schema的快速入門
創建一個schema文件,后綴名是“.xsd”
根節點<schema>
  1、在schema文件中
  屬性 xmlns="http://www.w3.org/2001/XMLSchema"
  -表示當前xml是一個約束文件
  targetNamespace="http://www.itcast.cn/201711111"
  -使用schema約束文件,直接通過這個地址引入約束文件
  elementFormDefault="qualified"
2、步驟:
①看xml中有多少個元素
  <element>
②看簡單元素和復雜元素
  如復雜元素:
<complexType>
  <sequence>
      子元素
  </sequence>
</complexType>
③簡單元素,寫在復雜元素的子元素位置
<element name="person">
    <complexType>
        <sequence>
            <element name="name" type="string"></element>
            <element name="age" type="int"></element>
        </sequence>
    </complexType>
</element>
  ④在被約束文件里面引入約束文件
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.itcast.cn/201711111"
xsi:schemaLocation="http://www.itcast.cn/201711111 1.xsd">
  • xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  --表示xml是一個被約束文件
  • xmlns="http://www.itcast.cn/201711111"   --是約束文檔中targetNamespace
  • xsi:schemaLocation="http://www.itcast.cn/201711111 1.xsd"  --targetNamespace 空格 約束文檔的地址
  3、XMLSchema復雜元素指示器
    • <sequence>:表示元素的出現的順序
    • <all>:元素只能出現一次
    • <choice>:元素只能出現其中的一個
    • maxOccurs="unbounded" :表示元素的出現的次數,如:<element name="name" type="string" maxOccurs="unbounded"></element>
    • <any></any>:表示任意元素
  可以約束屬性
    寫在復雜元素里面
    寫在</complexType>之前
    --
    <attribute name="id1" type="int" use="required"></attribute>
-name :屬性名稱
-type:屬性類型int string
-use:屬性是否必須出現 required
  4、復雜的schema約束
<company xmlns = "http://www.example.org/company"
xmlns:dept = "http://www.example.org/department"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://www.example.org/company company.xsd http://www.example.org/department denpartment.xsd">
*引入多個schema文件,可以給每個起一個別名
如:
<employee age="30">
  <!-- 部門名稱 -->
  <dept:name>100</dept:name>
  *想要引入部門的約束文件里的那么,使用部門的別名 detp:元素名稱
  <!-- 員工名稱 -->
  <name>張三</name>
</employee>
示例:
xml文檔
<?xml version="1.0" encoding="UTF-8" ?>
<person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.itcast.cn/201711111"
xsi:schemaLocation="http://www.itcast.cn/201711111 1.xsd">
    <name>zhangsan</name>
    <age>20</age>
</person>
xsd文檔
<?xml version="1.0" encoding="UTF-8" ?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://www.itcast.cn/201711111"
        elementFormDefault="qualified">
    <element name="person">
        <complexType>
            <sequence>
                <element name="name" type="string"></element>
                <element name="age" type="int"></element>
            </sequence>
        </complexType>
    </element>
</schema>
七、sax解析
1、sax解析
  解析xml有兩種技術 dom和sax
 
dom方式解析:
根據xml的層級結構在內存中分配一個樹形結構,
把xml的標簽,屬性和文本都封裝成對象
 
sax方式解析:
采用事件驅動,邊讀邊解析,
在java.xml.parsers包里面
  -SAXParser
  此類的實例可以從SAXParserFactory.newSAXParser()方法獲得
  -parse(File f,DefaultHandler dh)
    第一個參數:xml的路徑
    第二個參數:事件處理器
  -SAXParserFactory
    實例newInstance()方法得到
  sax執行過程:
2、使用jaxp的sax方式解析xml
sax方式不能實現增刪改操作,只能做查詢操作
打印出整個文檔
-執行parse方法,第一個參數xml路徑,第二個參數是事件處理器
-創建一個類,繼承事件處理器的類,重寫里面的三個方法
獲取到所有的name元素的值
-定義一個成員變量flag=false
-判斷開始方法是否是name元素,如果是name元素,把flag值設置成true
-如果flag值是true,在characters方法里面打印內容
-當執行到結束方法時候,把flag值設置成false
獲取第一個name元素的值
-定義一個成員變量idx=1
-在結束方法時候,idx++
-想要打印出第一個name元素的值,在characters方法里面判斷
 實例:
 1 import org.xml.sax.Attributes;
 2 import org.xml.sax.SAXException;
 3 import org.xml.sax.helpers.DefaultHandler;
 4 import javax.xml.parsers.SAXParser;
 5 import javax.xml.parsers.SAXParserFactory;
 6 
 7 public class TestSax {
 8     public static void main(String[] args) throws Exception {
 9         /*
10         * 1、創建解析工廠
11         * 2、創建解析器
12         * 3、執行parse方法
13         * 4、自己創建一個類,繼承DefaultHandler
14         * 5、重寫里面的三個方法
15         * */
16         SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
17         SAXParser saxParser = saxParserFactory.newSAXParser();
18         saxParser.parse("src/p1.xml",new MyDefault2());
19         saxParser.parse("src/p1.xml",new MyDefault1());
20     }
21 }
22 //實現獲取第一個name元素
23 class MyDefault2 extends DefaultHandler {
24     boolean flag = false;
25     int index = 1;
26     @Override
27     public void startElement(String uri, String localName, String qName, 
        Attributes attributes) throws SAXException {
28 //判斷qName是否是name元素 29 if ("name".equals(qName)) { 30 flag = true ; 31 } 32 } 33 @Override 34 public void characters(char[] ch, int start, int length) throws SAXException { 35 //當flag值是true時候,表示解析到name元素 36 if (flag == true && index == 1){ 37 System.out.println(new String(ch,start,length)); 38 } 39 } 40 @Override 41 public void endElement(String uri, String localName, String qName) throws SAXException { 42 //把flag設置成false,表示name元素結束 43 if ("name".equals(qName)) { 44 flag = false; 45 } 46 index++; 47 } 48 }
  //獲取所有name元素
49 class MyDefault1 extends DefaultHandler { 50 @Override 51 public void startElement(String uri, String localName, String qName, 52 Attributes attributes) throws SAXException { 53 System.out.print("<"+qName+">"); 54 } 55 @Override 56 public void characters(char[] ch, int start, int length) throws SAXException { 57 System.out.print(new String(ch,start,length)); 58 } 59 @Override 60 public void endElement(String uri, String localName, String qName) throws SAXException { 61 System.out.print("</"+ qName+">"); 62 } 63 }
xml文件:
<?xml version="1.0" encoding="UTF-8" ?>
<person>
    <p1>
        <name>zhangsan</name>
        <age>20</age>
    </p1>
    <p1>
        <name>lisi</name>
        <age>25</age>
    </p1>
</person>
八、使用dom4j解析xml
1、dom4j
  dom4j使用一個組織,針對xml解析,提供解析器dom4j,非javase的一部分,需導入jar包
  得到document
  SAXReader reader = new SAXReader();
  Document document = reader.read(url);
  document的父接口是Node
    如果在document里面找不到想要的方法,到Node里面去找
  document里面的方法getRootElement():獲取根節點返回的是Element
  Element也是一個接口,父接口是Node
    -Element和Node里面方法
    getParent():獲取父節點
    addElement:添加標簽
2、使用dom4j對xml進行增刪改查操作
①查詢所有name元素里面的值
步驟:
1、創建解析器
2、得到document
3、得到根節點 getRootElement()
4、得到所有的p1標簽
-element(qname)
  -表示獲取標簽下面的第一個子標簽
  -qname:標簽名稱
-elements(qname)
  -獲取標簽下面是這個名稱的所有子標簽(一層)
  -qname:標簽名稱
-elements()
  -獲取標簽下面的所有一層子標簽
5、得到name
6、得到name里面的值
 
  ②使用dom4j對xml進行增刪改查操作示例以及方法的封裝
  xml文檔:
<?xml version="1.0" encoding="UTF-8"?>
<person> 
  <p1 id1="aaa">
    <name>zhangsan</name>  
    <age>30</age>  
    <sex></sex> 
  </p1>  
  <p1> 
    <name>lisi</name>  
    <age>25</age> 
  </p1> 
</person>

  java文檔:

  1 package testDom4j;
  2 
  3 import dom4jutils.Dom4jUtils;
  4 import org.dom4j.Document;
  5 import org.dom4j.DocumentHelper;
  6 import org.dom4j.Element;
  7 import org.dom4j.io.OutputFormat;
  8 import org.dom4j.io.SAXReader;
  9 import org.dom4j.io.XMLWriter;
 10 
 11 import java.io.FileOutputStream;
 12 import java.util.List;
 13 
 14 public class TestDom4j {
 15     public static void main(String[] args) throws Exception {
 16 //        selectName();
 17 //        selectSin();
 18 //        selectSecond();
 19 //        addSex();
 20 //        addAgeBefore();
 21 //        modifyAge();
 22 //        deleteSchool();
 23         getValues();
 24     }
 25     //查詢xml中所有name元素的值
 26     public static void selectName() throws Exception{
 27         /*
 28         * 1、創建解析器
 29         * 2、得到document
 30         * 3、得到根節點  getRootElement() 返回Element
 31         * 4、得到所有的p1標簽
 32         *   -elements("p1") 返回Element
 33         * 5、得到name
 34         *   -在p1下面執行element("name")的方法返回Element
 35         * 6、得到name里面的值
 36         *   -getText方法得到值
 37         * */
 38         //創建解析器
 39         SAXReader reader = new SAXReader();
 40         //得到document
 41         Document document = reader.read("src/p1.xml");
 42         //得到根節點
 43         Element root = document.getRootElement();
 44         //得到p1
 45         List<Element> list = root.elements("p1");
 46         //遍歷list
 47         for(Element element : list) {
 48             //element是每一個p1
 49             //得到p1下面的name元素
 50             Element name1 = element.element("name") ;
 51             //得到name里面的值
 52             String s = name1.getText();
 53             System.out.println(s);
 54         }
 55     }
 56 
 57     //獲取得到第一個name元素的值
 58     public static void selectSin() throws Exception {
 59         /*
 60         * 1、創建解析器
 61         * 2、得到document
 62         * 3、得到根節點
 63         * 4、得到第一個p1標簽
 64         * 5、得到p1下面的name元素
 65         * 6、得到name里面的值
 66         * */
 67         Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
 68         Element root = document.getRootElement();
 69         Element p1 = root.element("p1");
 70         Element name1 = p1.element("name");
 71         System.out.println(name1.getText());
 72     }
 73     //獲取得到第二個name元素的值
 74     public static void selectSecond() throws Exception {
 75         /*
 76         * 1、創建解析器
 77         * 2、得到document
 78         * 3、得到根節點
 79         * 4、得到所有的p1
 80         * 5、遍歷得到第二p1
 81         * 6、得到第二個p1下面的name
 82         * 7、得到name的值
 83         * */
 84         Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
 85         Element root = document.getRootElement();
 86         List<Element> list = root.elements("p1");
 87         Element p2 = list.get(1);
 88         Element name2 = p2.element("name");
 89         System.out.println(name2.getText());
 90     }
 91 
 92     //在第一個p1標簽末尾添加一個元素<sex>女</sex>
 93     public static void addSex() throws Exception {
 94         /*
 95         * 1、創建解析器
 96         * 2、得到document
 97         * 3、得到根節點
 98         * 4、獲取第一個p1
 99         * 5、在p1下面添加元素
100         * 6、在添加完成之后的元素下面添加文本
101         * 7、回寫xml
102         * */
103         Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
104         Element root = document.getRootElement();
105         //得到第一個p1元素
106         Element p1 = root.element("p1");
107         //在p1下面直接添加元素
108         Element sex1 = p1.addElement("sex");
109         //在sex下面添加文本
110         sex1.setText("女");
111         //回寫xml
112         OutputFormat format = OutputFormat.createPrettyPrint();
113         XMLWriter xmlWriter = new XMLWriter(new FileOutputStream("src/p1.xml"),format);
114         xmlWriter.write(document);
115         xmlWriter.close();
116     }
117 
118     //在特定位置添加元素,在第一個p1下面的age標簽之前添加<school>ecit</school>
119     public static void addAgeBefore() throws Exception {
120         /*
121         * 1、創建解析器
122         * 2、得到document
123         * 3、得到根節點
124         * 4、獲取第一個p1
125         * 5、在p1下面所有的元素
126         * 6、在指定位置添加元素
127         * 7、回寫xml
128         * */
129         //獲得document
130         Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
131         Element root = document.getRootElement();
132         Element p1 = root.element("p1") ;
133         //獲取p1下所有元素的集合
134         List<Element> list = p1.elements();
135         //創建元素
136         Element school = DocumentHelper.createElement("school");
137         school.setText("ecit");
138         //在指定位置添加元素
139         list.add(1,school);
140         //回寫xml
141         Dom4jUtils.xmlWriters(Dom4jUtils.PATH,document);
142     }
143     //修改節點的操作,修改第一個p1下面的age元素值為30
144     public static void modifyAge() throws Exception {
145         /*
146         * 1、得到document
147         * 2、得到根節點
148         * 3、獲取第一個p1
149         * 4、得到p1下面的age
150         * 5、修改為30
151         * 6、回寫xml
152         * */
153         Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
154         Element root = document.getRootElement();
155         Element p1 = root.element("p1");
156         Element age = p1.element("age");
157         //使用setText()方法修改文本內容
158         age.setText("30");
159         Dom4jUtils.xmlWriters(Dom4jUtils.PATH,document);
160     }
161     //使用dom4j實現刪除節點的操作,刪除第一個p1下面的<school>ecit<school>元素
162     public static void deleteSchool() throws Exception{
163          /*
164         * 1、得到document
165         * 2、得到根節點
166         * 3、獲取第一個p1
167         * 4、得到第一個p1下面的school
168         * 5、刪除(使用p1刪除school)
169         * -得到school的父節點
170         *   -第一種直接得到p1
171         *   -使用方法getParent方法
172         * -在p1上面執行remove方法刪除節點
173         * 6、回寫xml
174         * */
175         Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
176         Element root = document.getRootElement();
177         Element p1 = root.element("p1");
178         Element sch = p1.element("school");
179         //通過父節點刪除
180         p1.remove(sch);
181         Dom4jUtils.xmlWriters(Dom4jUtils.PATH,document);
182     }
183     //使用dom4j獲取屬性的操作,獲取第一個p1的屬性id1的值
184     public static void getValues() throws Exception {
185          /*
186         * 1、得到document
187         * 2、得到根節點
188         * 3、獲取第一個p1
189         * 4、得到第一個p1的值
190         * */
191         Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
192         Element root = document.getRootElement();
193         Element p1 = root.element("p1");
194         String value = p1.attributeValue("id1");
195         System.out.println(value);
196     }
197 }

 

 1 package dom4jutils;
 2 
 3 import org.dom4j.Document;
 4 import org.dom4j.DocumentException;
 5 import org.dom4j.io.OutputFormat;
 6 import org.dom4j.io.SAXReader;
 7 import org.dom4j.io.XMLWriter;
 8 
 9 import java.io.FileOutputStream;
10 import java.io.IOException;
11 
12 public class Dom4jUtils {
13     public static final String PATH="src/p1.xml";
14     //返回document
15     public static Document getDocument(String path) {
16         try {
17             //創建解析器
18             SAXReader reader = new SAXReader();
19             //得到document
20             Document document = reader.read(path);
21             return document;
22         } catch (DocumentException e) {
23             e.printStackTrace();
24         }
25         return null;
26     }
27     //回寫xml
28     public static void xmlWriters(String path,Document document) {
29         try {
30             OutputFormat format = OutputFormat.createPrettyPrint();
31             XMLWriter xmlWriter = new XMLWriter(new FileOutputStream(path),format);
32             xmlWriter.write(document);
33             xmlWriter.close();
34         } catch (IOException e) {
35             e.printStackTrace();
36         }
37     }
38 }
3、使用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
  ①具體操作:
    默認情況下,dom4j不支持xpath,需導入jaxen-1.1-beta-6.jar
    在dom4j里面提供了兩個方法,用來支持xpath
      -selectNodes("xpath表達式") ,獲取多個節點
      -selectionSingleNode(“xpath”表達式),獲取一個節點
    *使用xpath實現:查詢xml中所有name元素的值
      -所有name元素的xpath表示://name
      -使用selectionNodes(“//name”);
    代碼和步驟:     
/*
* 1、得到document
* 2、直接使用selectNodes("//name")方法的到所有的name元素
* */
//得到document
Document document = Dom4jUtils.getDocument(Dom4jUtils.PATH);
//使用selectNodes("//name")方法得到所有的name元素
List<Node> list = document.selectNodes("//name");
for (Node node : list){
    //node是每一個name元素
    String s = node.getText();
    System.out.println(s);
}

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

    -//p1[@id1='aaa']/name
    -使用到selectSingleNode(“//p1[@id1='aaa']/name”)
九、實現簡單的學生管理系統
1、xml文檔,用於儲存信息:
<?xml version="1.0" encoding="UTF-8"?>
<student> 
  <stu> 
    <id>100</id>  
    <name>zhangsan</name>  
    <age>20</age> 
  </stu>  
  <stu> 
    <id>101</id>  
    <name>zhangsan</name>  
    <age>30</age> 
  </stu> 
</student>
2、構建service jar包用於查詢、添加、刪除方法的存儲
 1 package service;
 2 
 3 import org.dom4j.Document;
 4 import org.dom4j.Element;
 5 import org.dom4j.Node;
 6 import vo.Student;
 7 import java.util.List;
 8 
 9 public class StuService {
10 
11     //查詢 根據id查詢學生信息
12     public static Student getStu(String id) throws Exception {
13         /*
14         * 1、創建解析器
15         * 2、得到document
16         * 3、獲取所有的id
17         *
18         * 4、返回list集合,遍歷list集合
19         * 5、得到每一個id的節點
20         * 6、id節點的值
21         * 7、判斷id的值和傳遞的id值是否相同
22         * 8、如果相同,先獲取到id的父節點stu
23         * 9、通過stu獲取到name age值
24         * */
25         Document document = StudentUtils.getDocument(StudentUtils.PATH);
26         List<Node> list = document.selectNodes("//id");
27         Student student = new Student();
28         for (Node node : list) {
29              String idv = node.getText();
30              if (idv.equals(id)) {
31                 Element stu = node.getParent();
32                 String namev = stu.element("name").getText();
33                 String agev = stu.element("age").getText();
34                 student.setId(idv);
35                 student.setName(namev);
36                 student.setAge(agev);
37              }
38         }
39         return student;
40     }
41     //增加
42     public static void addStu(Student student) throws Exception {
43         /*
44         * 1、創建解析器
45         * 2、得到document
46         * 3、獲得根節點
47         * 4、在根節點上面創建stu標簽
48         * 5、在stu標簽上面依次添加id、name、age
49         * 6、在id name age上面依次添加值
50         * */
51         Document document = StudentUtils.getDocument(StudentUtils.PATH);
52         Element root = document.getRootElement();
53         Element stu = root.addElement("stu");
54         Element id1 = stu.addElement("id");
55         Element name1 = stu.addElement("name");
56         Element age1 = stu.addElement("age");
57         id1.setText(student.getId());
58         name1.setText(student.getName());
59         age1.setText(student.getAge());
60         StudentUtils.xmlWriters(StudentUtils.PATH,document);
61     }
62     //刪除,根據學生的id刪除
63     public static void delStu(String id) throws Exception{
64         /*
65         * 1、創建解析器
66         * 2、得到document
67         * 3、獲取所有的id
68         *   使用xpath //id 返回list集合
69         * 4、遍歷list集合
70         * 5、判斷集合里面的id和傳遞的id是否相同
71         * 6、如果相同,把id所在的stu刪除
72         * */
73         Document document = StudentUtils.getDocument(StudentUtils.PATH);
74         List<Node> list = document.selectNodes("//id");
75         for (Node node : list) {
76             String idv = node.getText();
77             if (idv.equals(id)) {
78                 Element stu = node.getParent();
79                 Element student = stu.getParent();
80                 student.remove(stu);
81             }
82         }
83         StudentUtils.xmlWriters(StudentUtils.PATH,document);
84     }
85 }
StuService操作類:
 1 package service;
 2 import org.dom4j.Document;
 3 import org.dom4j.DocumentException;
 4 import org.dom4j.io.OutputFormat;
 5 import org.dom4j.io.SAXReader;
 6 import org.dom4j.io.XMLWriter;
 7 import java.io.FileOutputStream;
 8 import java.io.IOException;
 9 
10 public class StudentUtils {
11     public static final String PATH="src/student.xml";
12     //返回document
13     public static Document getDocument(String path) {
14         try {
15             //創建解析器
16             SAXReader reader = new SAXReader();
17             //得到document
18             Document document = reader.read(path);
19             return document;
20         } catch (DocumentException e) {
21             e.printStackTrace();
22         }
23         return null;
24     }
25     //回寫xml
26     public static void xmlWriters(String path,Document document) {
27         try {
28             OutputFormat format = OutputFormat.createPrettyPrint();
29             XMLWriter xmlWriter = new XMLWriter(new FileOutputStream(path),format);
30             xmlWriter.write(document);
31             xmlWriter.close();
32         } catch (IOException e) {
33             e.printStackTrace();
34         }
35     }
36 }
3、構建對象的封裝包,用於對象設置與獲取。
 1 package vo;
 2 
 3 public class Student {
 4     private String id;
 5     private String name;
 6     private String age;
 7     public String getId() {return id; }
 8     public String getName() {return name;  }
 9     public String getAge() { return age;}
10     public void setId(String id) {this.id = id;}
11     public void setName(String name) { this.name = name;}
12     public void setAge(String age) { this.age = age;}
13 
14     @Override
15     public String toString() {
16         return "Student{" +
17                 "id='" + id + '\'' +
18                 ", name='" + name + '\'' +
19                 ", age='" + age + '\'' +
20                 '}';
21     }
22 }
4、構建測試包
 1 package test;
 2 
 3 import service.StuService;
 4 import vo.Student;
 5 
 6 public class TestStu {
 7     public static void main(String[] args) throws Exception{
 8         testSelect();
 9 //        testAdd();
10 //        testDel();
11     }
12     //測試查詢方法
13     public static void testSelect() throws Exception {
14         Student stu = StuService.getStu("100");
15         System.out.println(stu.toString());
16     }
17     //測試添加方法
18     public static void testAdd() throws Exception {
19         Student stu = new Student();
20         stu.setId("103");
21         stu.setName("wanwu");
22         stu.setAge("25");
23         StuService.addStu(stu);
24     }
25     //測試添加方法
26     public static void testDel() throws Exception{
27         StuService.delStu("103");
28     }
29 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM