本文將帶你領略一下XPath2.0的一些新特性。假定你已經對XPath1.0有了初步了解,并且經常在XSLT環境下使用它。在此并不準備對它作詳盡的描述,只是點出一些最值得關注的特性。
和 中都這樣說:“XPath是用于對XML文件的部分進行定址(addressing)的語言”。這是對XPath 1.0特性的恰當描述。(當然,這里沒有提到你可以使用算術表達式和字符串、數字和布爾表達式,但這些特性被盡可能地減到最少。)另一方面,人們對XPath2.0的特性所寄予的期望更多。XPath2.0是一個非常強大的語言,可操作的數據類型范圍更廣。對XPath2.0的較好的描述是: 它是一個處理序列的表達式語言,并內在地支持XML文件的查詢。查詢?這不是XQuery的任務嗎?
一年多以來,W3C的XSL 和XML Query 工作組就一直在一起工作,目標是在XSL2.0和XQuery1.0之間有盡可能多的共享內容,并且在技術和原則上可行,最后把這兩者之間的共同部分命名為"XPath 2.0"。這就意味著XPath2.0出臺的背后不但有,而且還包括許多。
XPath2.0是XQuery的一個嚴格的句法子集。事實上,工作草案和語言語法都是由同一個來源自動產生的(當然是用XML和XSLT)。雖然在嚴格意義上,一個工作草案不是另一個的子集(因為某些段落是專為XPath2.0而設的),但幾乎是一樣的。不管怎樣,中有80%的文本是這兩個草案中所共有的。 XQuery1.0的XPath2.0子集要大一些。從樂觀的角度看,一旦你在學習XPath2.0的過程中通過了所有障礙,就會欣喜地發現,你幾乎已經掌握了XQuery。
事實上,XQuery所獨有的特性主要是由頂層的查詢封裝機制組成。例如函數的定義、名稱空間的聲明、schema的引入以及元素的構建。而在XPath2.0的另一個主要使用環境XSLT2.0中,就不需要這些機制,因為XSLT2.0一般會提供自己的版本,所以就不把它包含在共有的子集中。
回顧一下,XPath1.0所支持的表達式只有四種類型:
關于XPath2.0表達式的返回值的種類的詳細資料,請參閱 文件。出于實用性,我們可以簡單地說,表達式的返回值可以是簡單類型、節點、節點或簡單類型序列。就像我們即將看到的,實際上每個表達式都返回一個序列。
XPath2.0中對節點的定義基本上與XPath1.0中相同,不同之處在于,現在可以將某些種類(元素和屬性)與XML Schema類型聯系起來并作為這些類型進行處理。與XPath1.0一樣,有7種節點類型:文件節點(document nodes), 元素(elements),屬性(attributes),名稱空間節點(namespace nodes),處理器指令(processing instructions),注釋(comments)和文本節點(text nodes)。在術語上有個小差別,在這里根節點("root nodes")現在有了個更加貼切的名稱 -- 文件節點("document nodes")。
作為一種處理序列的語言,讓我們來討論XPath2.0是如何對待序列的,以及它的表現。下面是一些準則,你應當牢記在心。這些關于序列的格言是XPath2.0工作的基礎。理解它們是深入理解并欣賞XPath2.0工作方式的前提。
如果你想要你的朋友對你留下深刻印象,就指著一個XPath2.0表達式(或XQuery表達式),然后不經意地說出這個表達式顯然返回一個序列。為使這個把戲逼真,你不必揭穿這個謎底:事實上所有表達式的返回值都是序列。
只要你明白這樣一個事實,即一切都是序列,你就會理解一個簡單類型值(或節點)和一個簡單類型值(或節點)序列之間沒有任何區別?;谶@樣的原因,XPath2.0工作草案和一般談論時經常說返回一個“數字”或“字符串”的表達式,實際上意味著“一個數值序列”或“一個字符串序列”。因為這兩者之間沒有區別,兩種用法都可接受。只需記住一切都是序列是沒錯的。
沒有序列之序列。如果你試圖在序列中嵌套序列,當然在句法上可以接受,不過你得到的是一個“膨脹的”序列,子序列和包含它的序列仍然是依次排列的。
例如,下面這個表達式
(2, 4, (1,2,3), 6)
經過取值變換后和這個表達式是同一個序列:
(2, 4, 1, 2, 3, 6)
以及這個表達式,諸如此類:
( (((2)), (4,1,2,3,(6)) )
…
與XPath1.0的節點集不同,序列是有序的??紤]下面這個表達式:
(/foo/bar, /foo)
就像你所知道的,逗號(,
)是一個構造(連接)序列的操作符。我將 /foo
放在 /foo/bar
之后,構造的序列中 bar
元素直接在 foo
元素之前,而不管它們在源文件中出現的先后次序。后邊,我們將會看到XPath2.0的序列可以取代XPath1.0的節點集,而不失功能性和兼容性。
與XPath1.0的節點集(或一般的集合)不同,序列內可以有重復。例如,我們稍微修改上面的表達式:
(/foo/bar, /foo, /foo/bar)
這個序列的組成是 bar
元素, 之后是 foo
元素,接著還是同樣的 bar
元素。在XPath1.0中,我們無法構造這樣的集合,因為根據定義,節點集內不能包含同樣的元素一次以上。
在XPath1.0中,如果你想處理多個節點,就必須和節點集打交道。在XPath2.0中,節點集的概念更趨一般化,并且作了擴展。正如我們所看到的,序列可以包含簡單類型值以及節點。我們還看到,序列和節點集的不同點在于它是有序的,并且可以有重復。人們自然會問:如何在不破壞XPath的同時處理節點集?
XPath1.0的節點集確實是無序的。然而,XSLT作為XPath的主要使用環境,節點集內的節點總是以某種次序進行處理的。處理節點集的缺省次序就是文件內的順序(因為所有節點的順序在文件內總是給定的)。在XPath2.0中,用以處理節點集合(即序列)的缺省順序未必和文件中的順序相同,但是和序列內的順序是一致的。為了與XPath1.0兼容,路徑表達式(以及其他1.0的表達式如聯合(union)表達式)被定義成總是返回文件內的順序。特別地,只要在直接表達式中使用"/",結果總是以文件內的順序。此外,總是自動從結果中除去重復的元素。XPath2.0就是這樣在一個只有序列的世界中模擬節點集的。
如果你還沒跟得上,也不必擔心。到目前為止,你可能還沒意識到XPath1.0的節點集是無序的。這對那些說明書的作者來說好處最大,它們確信一切都是一致的和完備定義(well-defined)的。姑且相信序列實際上是有序的,而路徑表達式仍然和從前一樣。
除了引入許多新的數據類型和函數, XPath2.0還引入了幾個基于關鍵字的運算符,我們來看看其中的幾個。
在XPath2.0處理序列的新運算符中,最強大的大概就是 for
表達式。它可以對序列進行列舉,為引用序列的每個成員返回一個新值。這一點與 xsl:for-each
很相似,不同之處在于它實際上返回的是一個序列,你然后可以按照序列對這個返回值進行操作。
我們來看下面的例子,它返回一個簡單類型的序列,每項都是各訂單中各個項目的總費用:
for $x in /order/item return $x/price * $x/quantity
然后我們就可以用 sum() 函數得到訂單的全部費用:
sum(for $x in /order/item return $x/price * $x/quantity)
與XSLT/XPath1.0相比,像這樣的情況在XPath2.0中使用序列非常容易解決。如果不使用序列,這個問題非常難辦,通常要構造一個臨時的“結果樹片斷”,然后使用 node-set()
擴展函數。
XPath2.0最強大(也是要求最多的)的結構之一就是條件表達式。這里是XPath2.0工作草案中的一個例子:
if ($widget1/unit-cost < $widget2/unit-cost) then $widget1 else $widget2XPath1.0的等于運算符(=
)是這個語言很有力的一個方面,這是因為它可以對節點集進行比較。我們來看這個例子:
/students/student/name = "Fred"
在XPath1.0中,如果任何一個學生的名字等于"Fred",這個表達式就返回true。這可以稱為存在定量(existential quantification)
,因為它測試滿足某種條件的成員是否存在。 XPath2.0保留了這項功能,還提供了更明確的測試方法:
some $x in /students/student/name satisfies $x = "Fred"
這個公式更加強大,因為你可以用任何想要的比較式來代替 $x = "Fred"
,而不僅僅是比較是否相等。而且,XPath1.0沒有提供一種手段來判斷是否每個學上的名字都是"Fred"。XPath2.0引入了這項功能來進行 全局定量(universal quantification), 所用的句法和上面的相似。
在XPath1.0中,唯一的集合運算符是聯合(|
)。這使得很難確定某個節點是否在給定的節點集內。例如,為了確定節點 $x
是否包含在 /foo/bar
節點集內,我們大約必須這么寫:
/foo/bar[generate-id(.)=generate-id($x)]
或者
count(/foo/bar)=count(/foo/bar | $x)
XPath2.0所引入的 intersect
運算符緩解了這種痛苦。上面的那種令人頭暈的寫法現在可以簡單地這么寫:
$x intersect /foo/bar
XPath2.0還引入了 except
運算符,馬上可以用來選擇某個節點集中除了某些節點之外的所有元素。在XPath1.0中如果要選擇除了某個特定名稱空間的名字之外的所有屬性,必須這樣寫:
如果你曾看過XPath2.0說明,會發現我沒有提到許多新關鍵字,包括 cast
, treat
, assert
, 和 instance of
。它們也是該語言的重要部分。但其重要性部分地取決于你在什么環境下使用XPath2.0。如果你打算在XSLT2.0環境下使用XPath,就沒有必要每天使用它們。在某種情況下你確實想使用它們(例如,將一個字符串轉換成日期),但不是非用不可。然而在XQuery1.0環境下
,你會很快熟悉它們的。
原因是XQuery1.0是設計為一種靜態類型的語言(statically typed language)。在執行查詢之前,要考慮查詢表達式的返回數據類型,并據此對查詢進行分析和優化。這只有在用戶明確指定了表達式的返回類型之后才有可能。這樣做的另一個好處是可以盡早地捕捉到錯誤,以便增強查詢的正確性。
當然,在可用性和類型安全性之間要有個取舍。為同時滿足兩個團體(有時人為地把使用者分為面向文檔的(document-oriented)和面向數據的(data-oriented)兩大類)的需要,XPath2.0提供了一種手段,讓使用環境可以決定在這種取舍之間站在何處。XPath2.0可以由其使用環境設置參數。這聽起來好像是解決可移植性的藥方。重要的是要清楚這些進展背后的指導原則。這個原則就是,任何XPath2.0表達式如果它不首先返回錯誤的話,則它的返回值應和其他環境下的返回值相同。這樣,如果一個表達式在一種環境下會產生錯誤,而在另一種環境下不會,則它不會產生兩個不同的表達式結果。換句話說,你得到的要么是正確答案,要么是錯誤信息。正確答案永遠不可能多于一個。
對XSLT的用戶而言,大多數情況下它們不必過分擔憂。一個XPath2.0的表達式在XQuery的環境下可能會拋出一個“異?!?,而在XSLT環境下同樣的表達式只是悄悄地調用一個后備轉換程序。
現在可以明確的是,XPath2.0是XPath1.0的一個非常重要的升級。它的發展動力既有XPath1.0用戶團體的要求,也有XQuery1.0對它的要求。也許你對整個方案不能認同,卻很難否認它代表了一個顯著的協同。再加上一些幸運的話,它同樣會成為幾種用戶團體的一個強大的標準工具。
国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97原文轉自:http://www.anti-gravitydesign.com