一佩迟、XML介紹
XML 指可擴(kuò)展標(biāo)記語言(EXtensible Markup Language),也是一種標(biāo)記語言,很類似 HTML.它的設(shè)計宗旨是傳輸數(shù)據(jù)竿屹,而非顯示數(shù)據(jù)它;標(biāo)簽沒有被預(yù)定義,需要自行定義標(biāo)簽报强。
XML 被設(shè)計為具有自我描述性,是 W3C 的推薦標(biāo)準(zhǔn),在電子計算機(jī)中,標(biāo)記指計算機(jī)所能理解的信息符號拱燃,通過此種標(biāo)記秉溉,計算機(jī)之間可以處理包含各種的信息比如文章等。它可以用來標(biāo)記數(shù)據(jù)碗誉、定義數(shù)據(jù)類型召嘶,是一種允許用戶對自己的標(biāo)記語言進(jìn)行定義的源語言。它非常適合萬維網(wǎng)傳輸哮缺,提供統(tǒng)一的方法來描述和交換獨(dú)立于應(yīng)用程序或供應(yīng)商的結(jié)構(gòu)化數(shù)據(jù)弄跌。是Internet環(huán)境中跨平臺的、依賴于內(nèi)容的技術(shù)尝苇,也是當(dāng)今處理分布式結(jié)構(gòu)信息的有效工具铛只。早在1998年埠胖,W3C就發(fā)布了XML1.0規(guī)范,使用它來簡化Internet的文檔信息傳輸淳玩。
xml的作用:
XML 是各種應(yīng)用程序之間進(jìn)行數(shù)據(jù)傳輸?shù)淖畛S玫墓ぞ咧背罚⑶以谛畔⒋鎯兔枋鲱I(lǐng)域變得越來越流行。簡單的說蜕着,我們在開發(fā)中使用XML主要有以下兩方面應(yīng)用:
a. XML做為數(shù)據(jù)交換的載體谊惭,用于數(shù)據(jù)的存儲與傳輸
b. XML做為配置文件
應(yīng)用場景:
- 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5">
<servlet>
<servlet-name>HelloMyServlet</servlet-name>
<servlet-class>cn.itcast.HelloMyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloMyServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
- 存放數(shù)據(jù)
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person id="p001">
<name>張三</name>
</person>
<person id="p002">
<name>李四</name>
</person>
</persons>
二、XML語法
書寫規(guī)范
xml必須有根元素(只有一個)
xml標(biāo)簽必須有關(guān)閉標(biāo)簽
xml標(biāo)簽對大小寫敏感
xml的屬性值須加引號
特殊字符必須轉(zhuǎn)義
xml中的標(biāo)簽名不能有空格
空格/回車/制表符在xml中都是文本節(jié)點(diǎn)
xml必須正確地嵌套
我們將符合上述書寫規(guī)則的XML叫做格式良好的XML文檔侮东。xml組成部分
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="WEB">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
對于一個xml文件,首先必須要有根元素豹芯,該元素是所有其它元素的父元素悄雅。而在xml中所有元素形成了一棵樹。父铁蹈,子及同胞等術(shù)語描述了元素之間的關(guān)系宽闲。所有的元素都可以擁有子元素。相同層級上的子元素成為同胞握牧。
所有元素都可以擁有文本內(nèi)容和屬性容诬。
Root 根元素
Element 元素
Attribute 屬性
Text 文本
在開發(fā)中,我們將上述內(nèi)容也統(tǒng)稱為Node(節(jié)點(diǎn))沿腰。
接下來,我們就分析一下览徒,對于一個xml文檔它的主要組成部分有哪些?
-
XML文檔聲明
<?xml version="1.0" encoding="UTF-8"?>- 文檔聲明必須為<?xml開頭,以?>結(jié)束颂龙;
- 文檔聲明必須從文檔的0行0列位置開始习蓬;
- 文檔聲明只有三個屬性:
a) versioin:指定XML文檔版本。必須屬性措嵌,因為我們不會選擇1.1躲叼,只會選擇1.0;
b) encoding:指定當(dāng)前文檔的編碼企巢》憧叮可選屬性,默認(rèn)值是utf-8浪规;
c) standalone:指定文檔獨(dú)立性或听。可選屬性罗丰,默認(rèn)值為yes神帅,表示當(dāng)前文檔是獨(dú)立文檔。如果為no表示當(dāng)前文檔不是獨(dú)立的文檔萌抵,會依賴外部文件找御。
-
元素
<servlet>- 元素是XML文檔中最重要的組成部分元镀,
- 普通元素的結(jié)構(gòu)開始標(biāo)簽、元素體霎桅、結(jié)束標(biāo)簽組成栖疑。例如:<hello>大家好</hello>
- 元素體:元素體可以是元素,也可以是文本滔驶,例如:<b><a>你好</a></b>
- 空元素:空元素只有開始標(biāo)簽遇革,而沒有結(jié)束標(biāo)簽,但元素必須自己閉合揭糕,例如:<c/>
- 元素命名:
a) 區(qū)分大小寫
b) 不能使用空格萝快,不能使用冒號:
c) 不建議以XML、xml著角、Xml開頭 - 良好的XML文檔揪漩,必須有一個根元素。
-
屬性
<web-app version="2.5">- 屬性是元素的一部分吏口,它必須出現(xiàn)在元素的開始標(biāo)簽中
- 屬性的定義格式:屬性名=屬性值奄容,其中屬性值必須使用單引或雙引
- 一個元素可以有0~N個屬性,但一個元素中不能出現(xiàn)同名屬性
- 屬性名不能使用空格产徊、冒號等特殊字符昂勒,且必須以字母開頭
注釋
XML的注釋與HTML相同,即以“”結(jié)束舟铜。注釋內(nèi)容會被XML解析器忽略戈盈!-
轉(zhuǎn)義字符
XML中的轉(zhuǎn)義字符與HTML一樣。
因為很多符號已經(jīng)被XML文檔結(jié)構(gòu)所使用谆刨,所以在元素體或?qū)傩灾抵邢胧褂眠@些符號就必須使用轉(zhuǎn)義字符奕谭,例如:“<”、“>”痴荐、“’”血柳、“””、“&”生兆。
- CDATA區(qū)
<![CDATA[
任意內(nèi)容
]]>
當(dāng)大量的轉(zhuǎn)義字符出現(xiàn)在xml文檔中時难捌,會使xml文檔的可讀性大幅度降低。這時如果使用CDATA段就會好一些鸦难。
在CDATA段中出現(xiàn)的“<”根吁、“>”、“””合蔽、“’”击敌、“&”,都無需使用轉(zhuǎn)義字符拴事。這可以提高xml文檔的可讀性沃斤。
在CDATA段中不能包含“]]>”圣蝎,即CDATA段的結(jié)束定界符。
三衡瓶、DTD約束
DTD(Document Type Definition)徘公,文檔類型定義,用來約束XML文檔哮针。規(guī)定XML文檔中元素的名稱关面,子元素的名稱及順序,元素的屬性等十厢。
開發(fā)中等太,我們很少自己編寫DTD約束文檔,通常情況我們都是通過框架提供的DTD約束文檔蛮放,編寫對應(yīng)的XML文檔澈驼。常見框架使用DTD約束有:struts2、hibernate等筛武。
DTD示例:
<?xml version="1.0" encoding="UTF-8"?>
<!--
模擬servlet2.3規(guī)范,如果開發(fā)人員需要在xml使用當(dāng)前DTD約束挎塌,必須包括DOCTYPE徘六。
格式如下:
<!DOCTYPE web-app SYSTEM "web-app_2_3.dtd">
-->
<!ELEMENT web-app (servlet*,servlet-mapping* , welcome-file-list?) >
<!ELEMENT servlet (servlet-name,description?,(servlet-class|jsp-file))>
<!ELEMENT servlet-mapping (servlet-name,url-pattern) >
<!ELEMENT servlet-name (#PCDATA)>
<!ELEMENT servlet-class (#PCDATA)>
<!ELEMENT url-pattern (#PCDATA)>
<!ELEMENT welcome-file-list (welcome-file+)>
<!ELEMENT welcome-file (#PCDATA)>
<!ATTLIST web-app version CDATA #IMPLIED>
案例實現(xiàn):通過提供的DTD“web-app_2_3.dtd”編寫XML
-
步驟1:創(chuàng)建web.xml文檔,并將“web-app_2_3.dtd”拷貝相同目錄下榴都。
-
步驟2:從DTD文檔開始處待锈,拷貝需要的“文檔聲明”
步驟3:完成xml內(nèi)容編寫
<web-app version="2.3">
<servlet>
<servlet-name></servlet-name>
<servlet-class></servlet-class>
</servlet>
<servlet-mapping>
<servlet-name></servlet-name>
<url-pattern></url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file></welcome-file>
<welcome-file></welcome-file>
<welcome-file></welcome-file>
</welcome-file-list>
</web-app>
DTD語法
- 文檔聲明
- 內(nèi)部DTD,在XML文檔內(nèi)部嵌入DTD嘴高,只對當(dāng)前XML有效竿音。
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<!DOCTYPE web-app [
... //具體的語法
]>
<web-app>
</web-app>
- 外部DTD—本地DTD,DTD文檔在本地系統(tǒng)上拴驮,公司內(nèi)部自己項目使用春瞬。
<?xml version="1.0" encoding="utf-8" standalone="no" ?>
<!DOCTYPE web-app SYSTEM "web-app_2_3.dtd">
<web-app>
</web-app>
- 外部DTD—公共DTD,DTD文檔在網(wǎng)絡(luò)上套啤,一般都有框架提供宽气。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
</web-app>
-
元素聲明
定義元素語法:<!ELEMENT 元素名 元素描述>
元素名:自定義
元素描述包括:符號和數(shù)據(jù)類型
常見符號:? * + () | ,
常見類型:#PCDATA 表示內(nèi)容是文檔,不能是子標(biāo)簽
<!ELEMENT web-app (servlet*,servlet-mapping* , welcome-file-list?) >
web-app 包括3個標(biāo)簽潜沦,且必須順序出現(xiàn)萄涯。
servlet子標(biāo)簽個數(shù)任意
servlet-mapping 子標(biāo)簽個數(shù)任意
welcome-file-list 子標(biāo)簽最多只能出現(xiàn)一次
<!ELEMENT servlet (servlet-name,description?,(servlet-class|jsp-file))>
servlet 有3個子標(biāo)簽,且必須順序出現(xiàn)
servlet-name唆鸡,必須有涝影,且只能出現(xiàn)一次
description,可選一次
servlet-class 和 jsp-file 二選一争占,且只能出現(xiàn)一次
<!ELEMENT servlet-name (#PCDATA)>
servlet-name 的標(biāo)簽體必須是文本
<!ELEMENT welcome-file-list (welcome-file+)>
welcome-file-list 至少有一個子標(biāo)簽welcome-file
- 屬性聲明
屬性的語法:
<!ATTLIST 元素名
屬性名 屬性類型 約束
屬性名 屬性類型 約束
...
>
元素名:屬性必須是給元素添加燃逻,所有必須先確定元素名
屬性名:自定義
屬性類型:ID序目、CDATA、枚舉 …
ID
: ID類型的屬性用來標(biāo)識元素的唯一性
CDATA
:文本類型
枚舉
:(e1 | e2 | ...) 多選一
約束:
#REQUIRED:說明屬性是必須的唆樊;
#IMPLIED:說明屬性是可選的宛琅;
<!ATTLIST web-app version CDATA #IMPLIED>
給web-app元素添加 version屬性,屬性值必須是文本逗旁,且可選嘿辟。
<web-app version="2.3"> 和 <web-app> 都符號約束
四、Schema約束
Schema是新的XML文檔約束片效;
Schema要比DTD強(qiáng)大很多红伦,是DTD 替代者;
Schema本身也是XML文檔淀衣,但Schema文檔的擴(kuò)展名為xsd昙读,而不是xml。
Schema 功能更強(qiáng)大膨桥,數(shù)據(jù)類型更完善
Schema 支持名稱空間
Schema與dtd區(qū)別:
XML從SGML中繼承了DTD蛮浑,并用它來定義內(nèi)容的模型,驗證和組織元素只嚣。同時沮稚,它也有很多局限:
? DTD不遵守XML語法;
? DTD不可擴(kuò)展册舞;
? DTD不支持名稱空間的應(yīng)用蕴掏;
? DTD沒有提供強(qiáng)大的數(shù)據(jù)類型支持,只能表示很簡單的數(shù)據(jù)類型调鲸。
Schema完全克服了這些弱點(diǎn)盛杰,使得基于Web的應(yīng)用系統(tǒng)交換XML數(shù)據(jù)更為容易。下面是它所展現(xiàn)的一些新特性:
? Schema完全基于XML語法藐石,不需要再學(xué)習(xí)特殊的語法即供;
? Schema能用處理XML文檔的工具處理,而不需要特殊的工具于微;
? Schema大大擴(kuò)充了數(shù)據(jù)類型募狂,支持boolean、numbers角雷、dates and times祸穷、URIs、integers勺三、decimal numbers和real numbers等雷滚;
? Schema支持原型,也就是元素的繼承吗坚。如:我們定義了一個“聯(lián)系人”數(shù)據(jù)類型祈远,然后可以根據(jù)它產(chǎn)生“朋友聯(lián)系人”和“客戶聯(lián)系”兩種數(shù)據(jù)類型呆万;
? Schema支持屬性組。我們一般聲明一些公共屬性车份,然后可以應(yīng)用于所有的元素谋减,屬性組允許把元素、屬性關(guān)系放于外部定義扫沼、組合出爹;
? 開放性。原來的DTD只能有一個DTD應(yīng)用于一個XML文檔缎除,現(xiàn)在可以有多個Schema運(yùn)用于一個XML文檔严就。
與DTD一樣,要求可以通過schema約束文檔編寫xml文檔器罐。常見框架使用schema的有:Spring等
實例:通過提供“web-app_2_5.xsd”編寫xml文檔
- web-app_2_5.xsd
<?xml version="1.0" encoding="UTF-8"?>
<!--
模擬servlet2.5規(guī)范梢为,如果開發(fā)人員需要在xml使用當(dāng)前Schema約束,必須包括指定命名空間轰坊。
格式如下:
<web-app xmlns="http://www.example.org/web-app_2_5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd"
version="2.5">
-->
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/web-app_2_5"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://www.example.org/web-app_2_5"
elementFormDefault="qualified">
<xsd:element name="web-app">
<xsd:complexType>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="servlet">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="servlet-name"></xsd:element>
<xsd:element name="servlet-class"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="servlet-mapping">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="servlet-name"></xsd:element>
<xsd:element name="url-pattern"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="welcome-file-list">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="welcome-file" maxOccurs="unbounded"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:choice>
<xsd:attribute name="version" type="double" use="optional"></xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:schema>
- 案例實現(xiàn)
-
步驟1:創(chuàng)建web.xml铸董,并將“web-app_2_5.xsd”拷貝到同級目錄
-
步驟2:從xsd文檔中拷貝需要的“命名空間”
完成xml內(nèi)容編寫
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://www.example.org/web-app_2_5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd"
version="2.5">
<servlet>
<servlet-name></servlet-name>
<servlet-class></servlet-class>
</servlet>
<servlet-mapping>
<servlet-name></servlet-name>
<url-pattern></url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file></welcome-file>
<welcome-file></welcome-file>
<welcome-file></welcome-file>
</welcome-file-list>
</web-app>
命名空間(語法)
如果一個XML文檔中使用多個Schema文件,而這些Schema文件中定義了相同名稱的元素時就會出現(xiàn)名字沖突肴沫。這就像一個Java文件中使用了import java.util.和import java.sql.時粟害,在使用Date類時,那么就不明確Date是哪個包下的Date了樊零。
總之名稱空間就是用來處理元素和屬性的名稱沖突問題,與Java中的包是同一用途孽文。如果每個元素和屬性都有自己的名稱空間驻襟,那么就不會出現(xiàn)名字沖突問題,就像是每個類都有自己所在的包一樣芋哭,那么類名就不會出現(xiàn)沖突沉衣。
約束文檔和XML關(guān)系
當(dāng)W3C提出Schema約束規(guī)范時,就提供“官方約束文檔”减牺。我們通過官方文檔豌习,必須“自定義schema 約束文檔”,開發(fā)中“自定義文檔”由框架編寫者提供拔疚。我們提供“自定義文檔”限定肥隆,編寫出自己的xml文檔。
聲明命名空間
默認(rèn)命名空間:<xxx xmlns=””> 稚失,使用<標(biāo)簽>
顯式命名空間:<xxx xmlns:別名=””> 栋艳, 使用<別名:標(biāo)簽>
實例:web-app_2_5.xsd
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" …>
表示自定義schema約束文檔引用官方文檔作為顯示命名空間。如果要使用官方提供的元素或?qū)傩跃涓鳎仨毷褂脁sd前綴(自定義吸占,此處表示官方文檔晴叨,所以使用xsd)
<xsd:schema>標(biāo)簽就有官方文檔提供,默認(rèn)命名空間直接使用矾屯。實例:web.xml
<web-app xmlns=http://www.example.org/web-app_2_5 …>
表示 xml 文檔引用“自定義約束文檔”作為默認(rèn)命名空間
因為使用默認(rèn)命名空間兼蕊,<web-app>直接使用自定義約束:web-app_2_5.xsd
<xsd:schema targetNamespace=http://www.example.org/web-app_2_5
表示給當(dāng)前自定義約束文檔進(jìn)行起名,提供給xml文檔使用件蚕。-
xml文檔:web.xml
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=http://www.example.org/web-app_2_5 web-app_2_5.xsdxmlns:xsi=”…” 固定寫法
表示是一個schema實例文檔孙技,就是被schema文檔約束的xml文檔。
xsi:schemaLocation=”名稱 路徑 名稱 路徑 名稱 路徑 …”
表示用于確定當(dāng)前xml文檔使用到的schema文檔的位置骤坐⌒餍樱“名稱 路徑”是成對出現(xiàn),與xmlns引用命名空間對應(yīng)纽绍。
五蕾久、dom4j解析
當(dāng)將數(shù)據(jù)存儲在XML后,我們就希望通過程序獲得XML的內(nèi)容拌夏。如果我們使用Java基礎(chǔ)所學(xué)習(xí)的IO知識是可以完成的僧著,不過你需要非常繁瑣的操作才可以完成,且開發(fā)中會遇到不同問題(只讀障簿、讀寫)盹愚。人們?yōu)椴煌瑔栴}提供不同的解析方式,并提交對應(yīng)的解析器站故,方便開發(fā)人員操作XML皆怕。
1. 解析方式和解析器
開發(fā)中比較常見的解析方式有三種,如下:
- DOM:(Document Object Model, 即文檔對象模型) 是 W3C 組織推薦的解析XML 的一種方式西篓。要求解析器把整個XML文檔裝載到內(nèi)存愈腾,并解析成一個Document對象。
a) 優(yōu)點(diǎn):元素與元素之間保留結(jié)構(gòu)關(guān)系岂津,故可以進(jìn)行增刪改查操作虱黄。
b) 缺點(diǎn):XML文檔過大,可能出現(xiàn)內(nèi)存溢出顯現(xiàn)吮成。 - SAX:(Simple API for XML) 不是官方標(biāo)準(zhǔn)橱乱,但它是 XML 社區(qū)事實上的標(biāo)準(zhǔn),幾乎所有的 XML 解析器都支持它粱甫。是一種速度更快泳叠,更有效的方法。它逐行掃描文檔茶宵,一邊掃描一邊解析析二。并以事件驅(qū)動的方式進(jìn)行具體解析,每執(zhí)行一行,都將觸發(fā)對應(yīng)的事件叶摄。
a) 優(yōu)點(diǎn):處理速度快属韧,可以處理大文件
b) 缺點(diǎn):只能讀,逐行后將釋放資源蛤吓。 - PULL:Android內(nèi)置的XML解析方式宵喂,類似SAX。(了解)
-
解析器:就是根據(jù)不同的解析方式提供的具體實現(xiàn)会傲。有的解析器操作過于繁瑣锅棕,為了方便開發(fā)人員,有提供易于操作的解析開發(fā)包淌山。
常見的解析開發(fā)包:
JAXP:sun公司提供支持DOM和SAX開發(fā)包
JDom:dom4j兄弟
jsoup:一種處理HTML特定解析開發(fā)包
dom4j:比較常用的解析開發(fā)包裸燎,hibernate底層采用。-
DOM和SAX區(qū)別
- DOM
支持回寫
會將整個XML載入內(nèi)存泼疑,以樹形結(jié)構(gòu)方式存儲
XML比較復(fù)雜的時候德绿,或者當(dāng)你需要隨機(jī)處理文檔中數(shù)據(jù)的時候不建議使用 - SAX
相比DOM是一種更為輕量級的方案
采用串行方法讀取 --- 逐行讀取
編程較為復(fù)雜
無法修改XML數(shù)據(jù)
- DOM
2. DOM解析原理及結(jié)構(gòu)模型
XML DOM 和 HTML DOM類似,XML DOM 將 整個XML文檔加載到內(nèi)存退渗,生成一個DOM樹移稳,并獲得一個Document對象,通過Document對象就可以對DOM進(jìn)行操作会油。
DOM中的核心概念就是節(jié)點(diǎn)个粱,在XML文檔中的元素、屬性翻翩、文本等都许,在DOM中都是節(jié)點(diǎn)!
3. API使用
如果需要使用dom4j嫂冻,必須導(dǎo)入jar包胶征。
dom4j 必須使用核心類SaxReader加載xml文檔獲得Document,通過Document對象獲得文檔的根元素絮吵,然后就可以操作了弧烤。
常用API如下:
- SaxReader對象
a) read(…) 加載執(zhí)行xml文檔 - Document對象
a) getRootElement() 獲得根元素 - Element對象
a) elements(…) 獲得指定名稱的所有子元素忱屑〉徘茫可以不指定名稱
b) element(…) 獲得指定名稱第一個子元素≥航洌可以不指定名稱
c) getName() 獲得當(dāng)前元素的元素名
d) attributeValue(…) 獲得指定屬性名的屬性值
e) elementText(…) 獲得指定名稱子元素的文本值
f) getText() 獲得當(dāng)前元素的文本內(nèi)容
節(jié)點(diǎn)操作
1.獲取文檔的根節(jié)點(diǎn).
Element root = document.getRootElement();
2.取得某個節(jié)點(diǎn)的子節(jié)點(diǎn).
Element element=node.element(“書名");
3.取得節(jié)點(diǎn)的文字
String text=node.getText();
4.取得某節(jié)點(diǎn)下所有名為“member”的子節(jié)點(diǎn)伴嗡,并進(jìn)行遍歷.
List nodes = rootElm.elements("member");
for (Iterator it = nodes.iterator(); it.hasNext();)
{ Element elm = (Element) it.next(); // do something}
節(jié)點(diǎn)對象屬性
1.取得某節(jié)點(diǎn)下的某屬性
Element root=document.getRootElement(); //屬性名name
Attribute attribute=root.attribute(“屬性”);//getValue()
2.取得屬性的文字
String text=attribute.getText(); === getValue();
3.取得某屬性的文字
String value=node.attributeValue(“屬性”);
解析web.xml文件:
public class Dom4jTest {
@Test
public void demo03() throws Exception{
//#1 獲得document
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File("src/com/yzy/mytomcat/schema/web.xml"));
//#2 獲得根元素
Element rootElement = document.getRootElement();
//打印version屬性值
String version = rootElement.attributeValue("version");
System.out.println(version);
//#3 獲得所有子元素。例如:<servlet>/<servlet-mapping>
List<Element> allChildElement = rootElement.elements();
//#4 遍歷所有
for (Element childElement : allChildElement) {
// #5.1 打印元素名
String childEleName = childElement.getName();
System.out.println(childEleName);
// #5.2 處理<servlet> ,并獲得子標(biāo)簽的內(nèi)容从铲。例如:<servlet-name> 等
if("servlet".equals(childEleName)){
// 方式1:獲得元素對象瘪校,然后獲得文本
Element servletNameElement = childElement.element("servlet-name");
String servletName = servletNameElement.getText();
System.out.println("\t" + servletName);
// 方式2:獲得元素文本值
String servletClass = childElement.elementText("servlet-class");
System.out.println("\t" + servletClass);
}
// #5.3 處理<servlet-mapping> 省略...
}
}
}
4. dom4j-xpath使用
XPath 是一門在 XML 文檔中查找信息的語言
XPath 可用來在 XML 文檔中對元素和屬性進(jìn)行遍歷
XPath簡化了Dom4j查找節(jié)點(diǎn)的過程
使用XPath必須導(dǎo)入jaxen-1.1-beta-6.jar否則出現(xiàn)NoClassDefFoundError: org/jaxen/JaxenException
在DOM4J中使用XPATH:
獲取所有符合條件的節(jié)點(diǎn)
selectNodes(String xpathExpression) 返回List集合
獲取符合條件的單個節(jié)點(diǎn)
selectSingleNode(String xpathExpression) 返回一個Node對象。
如果符合條件的節(jié)點(diǎn)有多個,那么返回第一個阱扬。
六泣懊、實例:編寫服務(wù)器軟件,訪問指定配置內(nèi)容
- 1.創(chuàng)建實例工廠
編寫接口
public interface MyServlet {
public void init(); //1.初始化
public void service(); //2.執(zhí)行
public void destory(); //3.銷毀
}
實現(xiàn)接口
public class HelloMyServlet implements MyServlet {
@Override
public void init() {
System.out.println("1.初始化");
}
@Override
public void service() {
System.out.println("2.執(zhí)行中....");
}
@Override
public void destory() {
System.out.println("3.銷毀");
}
}
測試麻惶,創(chuàng)建實現(xiàn)類實例對象
public class TestApp {
@Test
public void demo01(){
//手動創(chuàng)建執(zhí)行
MyServlet myServlet = new HelloMyServlet();
myServlet.init();
myServlet.service();
myServlet.destory();
}
}
- 反射創(chuàng)建實例對象
測試程序我們直接new HelloServlet馍刮,這種編程方式我們稱為硬編碼,及代碼寫死了窃蹋。為了后期程序的可擴(kuò)展卡啰,開發(fā)中通常使用實現(xiàn)類的全限定類名(cn.itcast.e_web.HelloMyServlet),通過反射加載字符串指定的類警没,并通過反射創(chuàng)建實例匈辱。
- 反射創(chuàng)建實例對象
@Test
public void demo02() throws Exception{
/* 反射創(chuàng)建執(zhí)行
* 1) Class.forName 返回指定接口或類的Class對象
* 2) newInstance() 通過Class對象創(chuàng)建類的實例對象,相當(dāng)于new Xxx();
*/
String servletClass = "com.yzy.mytomcat.web.implement.HelloMyServlet";
//3 獲得字符串實現(xiàn)類實例
Class clazz = Class.forName(servletClass);
MyServlet myServlet = (MyServlet) clazz.newInstance();
//4 執(zhí)行對象的方法
myServlet.init();
myServlet.service();
myServlet.destory();
}
- 解析xml
使用反射我們已經(jīng)可以創(chuàng)建對象的實例杀迹,此時我們使用的全限定類名亡脸,在程序是仍寫死了,我們將器配置到xml文檔中佛南。
xml文檔內(nèi)容:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://www.example.org/web-app_2_5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd"
version="2.5">
<servlet>
<servlet-name>HelloMyServlet</servlet-name>
<servlet-class>com.yzy.mytomcat.web.implement.HelloMyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloMyServlet</servlet-name>
<url-pattern>/implement</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file></welcome-file>
<welcome-file></welcome-file>
<welcome-file></welcome-file>
</welcome-file-list>
</web-app>
解析實現(xiàn)
@Test
public void demo03() throws Exception{
/* 讀取xml配置文件梗掰,獲得<servlet-class>配置的內(nèi)容,取代固定字符串
*/
//1.1 加載xml配置文件嗅回,并獲得document對象
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File("src/com/yzy/mytomcat/schema/web.xml"));
//1.2 獲得根元素
Element rootElement = document.getRootElement();
//1.3 獲得第一個<servlet> 子元素
Element servletElement = rootElement.element("servlet");
//1.4 獲得字符串實現(xiàn)類 <servlet-class>的值
String servletClass = servletElement.elementText("servlet-class");
//3 獲得字符串實現(xiàn)類實例
Class clazz = Class.forName(servletClass);
MyServlet myServlet = (MyServlet) clazz.newInstance();
//4 執(zhí)行對象的方法
myServlet.init();
myServlet.service();
myServlet.destory();
}
- 模擬瀏覽器路徑
上面我們已經(jīng)解析xml及穗,不過我們獲得內(nèi)容是固定。我們希望如果用戶訪問的路徑是/implement
绵载,將執(zhí)行com.yzy.mytomcat.web.implement.HelloMyServlet
程序埂陆,如果訪問時/implement2
,將執(zhí)行com.yzy.mytomcat.web.implement.HelloMyServlet2
程序娃豹。
在執(zhí)行測試程序前(@Before)焚虱,解析xml文件,將解析的結(jié)果存放在Map中懂版,map中數(shù)據(jù)的格式為:路徑=實現(xiàn)類鹃栽。
- 模擬瀏覽器路徑
xml文件內(nèi)容:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://www.example.org/web-app_2_5"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.example.org/web-app_2_5 web-app_2_5.xsd"
version="2.5">
<servlet>
<servlet-name>HelloMyServlet</servlet-name>
<servlet-class>com.yzy.mytomcat.web.implement.HelloMyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloMyServlet</servlet-name>
<url-pattern>/implement</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>HelloMyServlet2</servlet-name>
<servlet-class>com.yzy.mytomcat.web.implement2.HelloMyServlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloMyServlet2</servlet-name>
<url-pattern>/implement2</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file></welcome-file>
<welcome-file></welcome-file>
<welcome-file></welcome-file>
</welcome-file-list>
</web-app>
解析xml思路:先解析<servlet>,將結(jié)果存放map躯畴,name=class民鼓,然后再解析<servlet-mapping>通過name獲得class,再將url=class存放到map蓬抄,最后將name=class移除丰嘉。
//最終存放 key=請求路徑,value=實現(xiàn)類
private Map<String, String> data = new HashMap<String,String>();
@Before
public void demo04Before() throws Exception{
//在執(zhí)行前執(zhí)行嚷缭,解析xml饮亏,并將結(jié)果存放到Map<路徑耍贾,實現(xiàn)類>中
//1 獲得document
SAXReader saxReader = new SAXReader();
Document document = saxReader.read(new File("src/com/yzy/mytomcat/schema/web.xml"));
//2 獲得根元素
Element rootElement = document.getRootElement();
//3 獲得所有的子元素 <servlet> 、<servlet-mapping>等
List<Element> allChildElement = rootElement.elements();
/* 4 遍歷所有
* 1)解析到<servlet>路幸,將其子標(biāo)簽<servlet-name>與<servlet-class>存放到Map中
* 2)解析到<servlet-mapping>荐开,獲得子標(biāo)簽<servlet-name>和<url-pattern>, 從map中獲得1的內(nèi)容,組合成 url = class 鍵值對
*/
for (Element childElement : allChildElement) {
//4.1 獲得元素名
String eleName = childElement.getName();
//4.2 如果是servlet简肴,將解析內(nèi)容存放到Map中
if("servlet".equals(eleName)){
String servletName = childElement.elementText("servlet-name");
String servletClass = childElement.elementText("servlet-class");
data.put(servletName, servletClass);
}
//4.3 如果是servlet-mapping誓焦,獲得之前內(nèi)容,組成成key=url,value=class并添加到Map中
if("servlet-mapping".equals(eleName)){
String servletName = childElement.elementText("servlet-name");
String urlPattern = childElement.elementText("url-pattern");
// 獲得<servlet-name>之前存放在Map中<servlet-class>值
String servletClass= data.get(servletName);
// 存放新的內(nèi)容 url = class
data.put(urlPattern, servletClass);
// 將之前存放的數(shù)據(jù)刪除
data.remove(servletName);
}
//打印信息
System.out.println(data);
}
}
模擬瀏覽器請求路徑着帽,通過url從map獲得class杂伟,并使用反射執(zhí)行實現(xiàn)類。
@Test
public void demo04() throws Exception{
//1 模擬路徑
//String url = "/implement";
String url = "/implement2";
//2 通過路徑獲得對應(yīng)的實現(xiàn)類
String servletClass = data.get(url);
//3 獲得字符串實現(xiàn)類實例
Class clazz = Class.forName(servletClass);
MyServlet myServlet = (MyServlet) clazz.newInstance();
//4 執(zhí)行對象的方法
myServlet.init();
myServlet.service();
myServlet.destory();
}
- 瀏覽器訪問
使用Socket編寫服務(wù)仍翰,通過瀏覽器可以訪問赫粥,并解析瀏覽器發(fā)送的請求數(shù)據(jù),最終獲得請求路徑予借。
訪問路徑:
http://localhost:8888/implement
http://localhost:8888/implement2
- 瀏覽器訪問
@Test
public void demo05() throws Exception{
//使用socket獲得請求路徑
//1.1 給本地計算機(jī)綁定端口8888
ServerSocket serverSocket = new ServerSocket(8888);
//1.2 程序阻塞越平,等待瀏覽器請求。
Socket accept = serverSocket.accept();
//1.3 獲得請求所有數(shù)據(jù)
BufferedReader reader = new BufferedReader(new InputStreamReader(accept.getInputStream()));
//1.4 獲得第一行數(shù)據(jù)灵迫,請求行秦叛,例如:GET /hello HTTP/1.1
String firstLine = reader.readLine();
//1.5 請求行三部分?jǐn)?shù)據(jù)由空格連接,獲得中間數(shù)據(jù)瀑粥。表示請求路徑
String url = firstLine.split(" ")[1];
System.out.println(url);
//2 通過路徑獲得對應(yīng)的實現(xiàn)類
String servletClass = data.get(url);
//3 獲得字符串實現(xiàn)類實例
Class clazz = Class.forName(servletClass);
MyServlet myServlet = (MyServlet) clazz.newInstance();
//4 執(zhí)行對象的方法
myServlet.init();
myServlet.service();
myServlet.destory();
//5 釋放資源
reader.close();
控制臺等待鏈接時:
輸入網(wǎng)址測試挣跋,控制臺效果: