XPath 2.0 的新特性 (轉)
XPath 2.0 的新特性
關鍵字: XPath 2, XQuery, XML原作:2002.4.20, to:fwjsoft@.com.cn">onestab 譯自
本文將帶你領略一下XPath2.0的一些新特性。假定你已經對XPath1.0有了初步瞭解,並且經常在T環境下使用它。在此並不準備對它作詳盡的描述,只是點出一些最值得關注的特性。
XPath1.0 和 XPath2.0的相互關係
和 中都這樣說:“XPath是用於對XML的部分進行定址(addressing)的語言”。這是對XPath 1.0特性的恰當描述。(當然,這裡沒有提到你可以使用算術和字串、數字和布林表示式,但這些特性被儘可能地減到最少。)另一方面,人們對XPath2.0的特性所寄予的期望更多。XPath2.0是一個非常強大的語言,可操作的資料型別範圍更廣。對XPath2.0的較好的描述是: 它是一個處理序列的表示式語言,並內在地支援XML檔案的查詢。查詢?這不是XQuery的任務嗎?
XPath2.0 和 XQuery1.0的相互關係
一年多以來,的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一般會提供自己的版本,所以就不把它包含在共有的子集中。
對XML Schema的支援
回顧一下,XPath1.0所支援的表示式只有四種型別:
- 節點集
- 布林值
- 數字(浮點數)
- 字串
關於XPath2.0表示式的返回值的種類的詳細資料,請參閱 檔案。出於實用性,我們可以簡單地說,表示式的返回值可以是簡單型別、節點、節點或簡單型別序列。就像我們即將看到的,實際上每個表示式都返回一個序列。
XPath2.0中對節點的定義基本上與XPath1.0中相同,不同之處在於,現在可以將某些種類(元素和屬性)與XML Schema型別聯絡起來並作為這些型別進行處理。與XPath1.0一樣,有7種節點型別:檔案節點(document nodes), 元素(elements),屬性(attributes),名稱空間節點(namespace nodes),指令(processing instructions),註釋(comments)和文字節點(text nodes)。在術語上有個小差別,在這裡根節點(" 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還引入了幾個基於關鍵字的運算子,我們來看看其中的幾個。
對序列的運算(Operations on sequences)
在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 $widget2
定量修飾符(Quantifiers)
XPath1.0的等於運算子(=
)是這個語言很有力的一個方面,這是因為它可以對節點集進行比較。我們來看這個例子:
/students/student/name = "Fred"
在XPath1.0中,如果任何一個學生的名字等於"Fred",這個表示式就返回true。這可以稱為存在定量(existential quantification) ,因為它測試滿足某種條件的成員是否存在。 XPath2.0保留了這項功能,還提供了更明確的測試方法:some $x in /students/student/name satiies $x = "Fred"
這個公式更加強大,因為你可以用任何想要的比較式來代替$x = "Fred"
,而不僅僅是比較是否相等。而且,XPath1.0沒有提供一種手段來判斷是否每個學上的名字都是"Fred"。XPath2.0引入了這項功能來進行 全域性定量(universal quantification), 所用的句法和上面的相似。
every $x in /students/student/name satisfies $x = "Fred"
交,差,聯合 (Intersections, differences, unions)
在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中如果要選擇除了某個特定名稱空間的名字之外的所有屬性,必須這樣寫:
@*[not(namespace-uri()='' and local-name()='foo')]
或@*[not(generate-id(.)=generate-id(../@exc:foo)]
這時候,XPath2.0就會再救你一命,你可以用下面這種簡潔的方式寫:@* except @exc:foo
對資料型別的擔憂
如果你曾看過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對它的要求。也許你對整個方案不能認同,卻很難否認它代表了一個顯著的協同。再加上一些幸運的話,它同樣會成為幾種使用者團體的一個強大的標準工具。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-992087/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- XSLT 2.0 的新特性 (轉)
- Django 2.0 新特性Django
- 〔譯〕TypeScript 2.0 的新特性TypeScript
- C++ 2.0新特性C++
- Firebug 2.0新特性
- C# 2.0 新特性C#
- Entity Framework Core 2.0 新特性Framework
- HTTP----HTTP2.0新特性HTTP
- Ruby 2.0 有哪些新特性?
- 淺談RxJava與2.0的新特性RxJava
- AngularJS 2.0會有哪些新特性?AngularJS
- InterBase 6.5的新特性 (轉)
- PHP 7.4 新特性 —— 箭頭函式 2.0PHP函式
- 玩轉iOS開發:iOS 11 新特性《Layout的新特性》iOS
- Fedora Core 6的新特性(轉)
- 創新觸手可及: WebSphere CloudBurst V2.0 新特性WebCloud
- JBUILDER 5 新特性 (轉)UI
- C++2.0——語言新特性之Variadic TemplatesC++
- Spring Boot 2.0 新特性(二):新增事件ApplicationStartedEventSpring Boot事件APPdev
- 玩轉iOS開發:iOS 11 新特性《UIKit新特性的基本認識》iOSUI
- 【轉】http2 新特性HTTP
- 在Vue3.0之前,回顧Vue2.0新特性的使用Vue
- vue2.0的基本特性Vue
- Delphi6的新特性[翻譯] (轉)
- 官方解讀:TensorFlow 2.0中即將到來的所有新特性
- 玩轉ES6新特性
- 【轉】Spring Framework 5.0 新特性SpringFramework
- 11GR2新特性(轉)
- Spring3.1新特性(轉)Spring
- C# 6.0新特性(轉載)C#
- Java新特性--Java Web Start (轉)JavaWeb
- [轉載] Java7中增加的新特性Java
- Oracle10g新特性——RMAN(轉來的)Oracle
- 10g新特性——Data Pump(轉)
- Oracle 11g 新特性(轉載)Oracle
- 號外:Delphi6新特性! (轉)
- 號外:Delphi6 新特性 !!!! (轉)
- JDBC 3.0 有什麼新特性 (轉)JDBC