XPathXPath 簡介XPath 是一門在 XML 文檔中查找信息的語言。XPath 可用來在 XML 文檔中對元素和屬性進(jìn)行遍歷。XPath 是 W3C XSLT 標(biāo)準(zhǔn)的主要元素,并且 XQuery 和 XPointer 同時被構(gòu)建于 XPath 表達(dá)之上。因此,對 XPath 的理解是很多高級 XML 應(yīng)用的基礎(chǔ)。 其實(shí)對些我們并不陌生,最與XPath相似的便是CSS的選擇器.在CSS中使用CSS選擇符選擇元素來應(yīng)用樣式,而在XSLT中則使用XPath,XPath與CSS選擇器相比如強(qiáng)大的許多!下面是CSS選擇符與XPath選擇符一些對照: //CSS選擇符 body p //選擇所有body下面的p元素 body>p //選擇body的子元素p * //選擇所有的元素 //與之對應(yīng)的XPath選擇符 body//p body/p * 雖然現(xiàn)在還不能了解這些XPath表達(dá)的含意,但可以發(fā)現(xiàn),它和CSS選擇符十分相像!但XPath有更強(qiáng)大的地方,比如它可以定位到body元素下具體位置上的p或可以選擇前N個p: body/p[position()=4] //這個XPath表達(dá)式將選取body子元素中第4個p元素,注意這里從1開始計數(shù) body/p[position()<3] //將選取body子元素中前兩個p元素 XPath 使用路徑表達(dá)式來選取 XML 文檔中的節(jié)點(diǎn)或者節(jié)點(diǎn)集。這些路徑表達(dá)式和我們在常規(guī)的電腦文件系統(tǒng)中看到的表達(dá)式非常相似。另外,XPath 含有超過 100 個內(nèi)建的函數(shù)。這些函數(shù)用于字符串值、數(shù)值,日期和時間比較、節(jié)點(diǎn)和 QName 處理、序列處理、邏輯值等等。 書寫XPathXPath使用路徑表達(dá)式在 XML 文檔中選取節(jié)點(diǎn)。節(jié)點(diǎn)是通過沿著路徑(path)或者 步(step) 來選取的。如"/"表示文檔節(jié)點(diǎn),"."表示當(dāng)前節(jié)點(diǎn),而".."則表示當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn).示例: {因?yàn)閄Path表示達(dá)式中有斜杠,所以暫時用這個表示注釋! / {選取文檔節(jié)點(diǎn),nodeType為9 /root {選取文檔根元素,類似于文件系統(tǒng)的路徑(Unix),以/開頭的路徑都是絕對路徑 /root/child/.. {選取根節(jié)點(diǎn)root的子節(jié)點(diǎn)child的父節(jié)點(diǎn)(就是root) 下面是一些常用路徑表達(dá)式
<?xml version="1.0"?> <root> <child attr="attr" /> <child> <a><desc /></a> </child> </root> {針對上面的XML文檔的XPath結(jié)果,當(dāng)前節(jié)點(diǎn)為document /root {選取root root {選取root child {空,因?yàn)閏hild不是document的子元素 //child {選取兩個child元素,//表示后代 //@attr {選取attr屬性節(jié)點(diǎn) /root/child//desc {返回child的后代元素desc 謂語(Predicates)謂語用于在查找節(jié)點(diǎn)時提供更詳盡的信息,謂語被嵌在方括號中。下面是一些帶有謂語的XPath表達(dá)式: /root/child[3] {選取root元素的第三個child子元素,注意,這和數(shù)組下標(biāo)不一樣,從1開始計數(shù) //child[@attr] {選取所有具有屬性attr的child元素 //child[@attr="val"]/desc {選取所有屬性attr的值為val的child元素的子元素desc //child[desc] {選取所有的有desc子元素的child //child[position()>3] {position()是XPath中的一個函數(shù),表示節(jié)點(diǎn)的位置 //child[@attr>12] {XPath表達(dá)式還可以進(jìn)行數(shù)值比較,該表達(dá)式將選取attr屬性值大于12的child元素 //child[last()] {last()函數(shù)返回節(jié)點(diǎn)列表最后的位置,該表達(dá)式將選取最后一個child元素 通配符XPath 通配符可用來選取未知的 XML 元素。
/root/* {選取根元素下面的所有子元素 /root/node() {選取根元素下面的所有節(jié)點(diǎn),包括文本節(jié)點(diǎn) //* {選取文檔中所有元素 //child[@*] {選取所有具有屬性的child元素 //@* {選取所有的屬性節(jié)點(diǎn) 組合路徑與CSS中使用逗號組合使用多個選擇符一樣,XPath支持一種使用"|"來組合多個路徑的語法! /root | /root/child {選取根元素root與它下面的子元素child //child | //desc {選取所有的child元素與desc元素 XPath 運(yùn)算符下面列出了可用在 XPath 表達(dá)式中的運(yùn)算符:
XPath 軸軸可定義某個相對于當(dāng)前節(jié)點(diǎn)的節(jié)點(diǎn)集。下面一可用的軸名稱與對應(yīng)的結(jié)果:
事實(shí)上,一個完整的XPath表達(dá)式由"/"與"步"構(gòu)成的,而步又是由 "軸" 、 "節(jié)點(diǎn)測試"和"謂語"構(gòu)成的.如下: step/step/..... {一個XPath表達(dá)式 {step的構(gòu)成 軸名稱::節(jié)點(diǎn)測試[謂語] 在一般的XPath表達(dá)式中,沒有謂語即表達(dá)沒有其它條件限制,而沒有軸名稱,則默認(rèn)使用child.如"abc"與"child::abc"是等效的, 下面是一些與使用軸名稱等效的簡單XPath表達(dá)式:
XPath還包含一套函數(shù)庫,如position與last就是函數(shù),一般的函數(shù)被用在謂語中,而在XSLT及XQuery中它們則得到了更廣泛的使用. 瀏覽器中的XPathIE瀏覽器對XPath的實(shí)現(xiàn)比較簡單.一個XML DOM對象(及每個節(jié)點(diǎn))都有selectSingleNode與selectNodes方法,傳入XPath表達(dá)式,selectNodes返回匹配的節(jié)點(diǎn)列表,而selectSingleNode則只返回列表中第一個項(xiàng)目! var xmlDom = getXMLDOM();//我們之前寫的跨瀏覽器的XML DOM加載函數(shù) loadXMLFile(xmlDom,"text.xml"); var root = xmlDom.selectSingleNode("/*");//返回文檔根元素 root = xmlDom.selectNodes("/*")[0];//同上 var lastChild = xmlDom.selectSingleNode("/*/*[last()]"); Mozilla是根據(jù)DOM標(biāo)準(zhǔn)來實(shí)現(xiàn)對XPath的支持的。DOM Level 3附加標(biāo)準(zhǔn)DOM Level 3 XPath定義了用于在DOM中計算XPath表達(dá)式的接口。遺憾的是,這個標(biāo)準(zhǔn)要比微軟直觀的方式復(fù)雜得多。 雖然有好多與XPath相關(guān)的對象,最重要的兩個是:XPathEvaluator和XPathResult。XPathEvaluator利用方法evaluate()計算XPath表達(dá)式。 evaluate()方法有五個參數(shù):XPath表達(dá)式、上下文節(jié)點(diǎn)、命名空間解釋程序和返回的結(jié)果的類型,同時,在XPathResult中存放結(jié)果(通常為null)。 命名空間解釋程序,只有在XML代碼用到了XML命名空間時才是必要的,所以通常留空,置為null。返回結(jié)果的類型,可以是以下十個常量值之一:
下面是使用ORDERED_NODE_ITERATOR_TYPE的例子: var xmlDom = getXMLDOM();//我們之前寫的跨瀏覽器的XML DOM加載函數(shù) loadXMLFile(xmlDom,"text.xml"); var evaluator = new XPathEvaluator(); var result =evaluator.evaluate("/root",xmlDom,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null); var node; if (result) {//執(zhí)行失敗會返回null while(node=result.iterateNext()) {//這個列表必須使用iterateNext方法遍歷 alert(node.tagName); } } |
|