黃聰:C#操作xml SelectNodes,SelectSingleNode通過 xPath 定位class包含Contains的DIV

來源:互聯網
上載者:User

標籤:

原文:http://ejohn.org/blog/xpath-css-selectors

最近,我做了很多工作來實現一個同時支援XPath和CSS 3的解析器,令我驚訝的是:它們倆在某些方面上非常相似,而在另一些方面上又完全不同.不同的地方有,CSS是用來配合HTML工作的,可以使用#id來根據ID擷取元素,以及使用.class來根據class擷取元素.這些用XPath實現的話都不會那麼簡潔,反過來呢,XPath可以使用..來返回到DOM樹的上層節點中,還可以使用foo[bar]來擷取到一個擁有bar子項目的foo元素.CSS選取器完全做不到這些,總結一下就是,和XPath比起來,CSS選取器通常都比較短小,但可惜的是不夠強大.

我認為將這兩種選取器的寫法做一個比較是很有價值的.

目標 CSS 3 XPath
所有元素 * //*
所有的P元素 p //p
所有的p元素的子項目 p > * //p/*
根據ID擷取元素 #foo //*[@id=‘foo‘]
根據Class擷取元素 .foo                                //*[contains(@class,‘foo‘)] 1
擁有某個屬性的元素 *[title] //*[@title]
所有P元素的第一個子項目 p > *:first-child //p/*[0]

所有擁有子項目a的P元素

無法實現 //p[a]
下一個兄弟元素 p + * //p/following-sibling::*[0]

從文法上看,我非常驚訝這兩種選取器在某些情況下的相似性,尤其是‘>‘和‘/‘兩者之間.雖然他們並不總是有著相同的功能(XPath中要取決於正在使用的軸),但通常情況下他們指的都是某個父元素的子項目.還有,空白符‘ ‘和‘//‘都意味著當前元素的所有後代元素.最後是星號‘*‘,類似於萬用字元,表示所有元素,而不管是哪種標籤名.

1 這個寫法其實不正確,因為它不光會匹配到我們想要的‘foo bar‘,還會意外的匹配到‘foobar‘.正確的寫法可能會非常複雜,可能會需要用到多個運算式才能完成.下面是譯者注:上表中錯誤的XPath:
//*[contains(@class,‘foo‘)]
我實現的寫法是:
//*[@class=‘foo‘ or contains(@class,‘ foo ‘) or starts-with(@class,‘foo ‘) or substring(@class,string-length(@class)-3)=‘ foo‘]

比起CSS的.foo,真的是好複雜,我來解釋一下,一個元素的class屬性中如果包含‘foo‘,可能有四種情況,列出表來是這樣的:

class="foo" //*[@class=‘foo‘] class屬性只有一個值foo
class="foobar foo bar" //*[@class=‘ foo ‘] class屬性值中,foo在其他兩邊的值的中間

class="foo bar"

//*[starts-with(@class,‘foo ‘)] class屬性值中,foo在最左邊
class="bar foo" //*[substring(@class,string-length(@class)-3)=‘ foo‘] class屬性值中,foo在最右邊,XPath1.0中沒有ends-with函數,2.0有,現在瀏覽器實現的都是1.0

那麼我們能在網頁開發中用上XPath嗎?最初,jQuery是支援XPath選取器的,但後來,由於效率問題,jQuery放棄了對XPath的支援.剛好,Google在上個月發布了Wicked Good XPath,這是一個DOM Level 3 XPath規範的純JavaScript實現,也是目前同類實現中最快的,我們可以把這個指令碼和jQuery結合起來使用.

jQuery.getScript("http://wicked-good-xpath.googlecode.com/files/wgxpath.install.js").success(function () {    //載入庫檔案
wgxpath.install(); //安裝XPath支援
jQuery.xpath = function (xpath) { var elements = []; //用來儲存XPath選擇到的元素
var xpathResult = document.evaluate(xpath, document, null, 6, null); for (var i = 0; i < xpathResult.snapshotLength; i++) { elements.push(xpathResult.snapshotItem(i)); } return jQuery(elements); //傳給jQueryFactory 方法,返回jQuery對象
}})

這樣就能通過$.xpath()靜態方法來選擇元素了,該方法返回的也是一個jQuery對象,和使用$()沒什麼差別.本頁面已經載入了這個指令碼,你可以現在開啟控制台實驗一下$.xpath方法.

那我們有了CSS選取器,為什麼還要用XPath呢,答案是:有些時候,XPath更強大一點.比如:

在上面John Resig總結的表中,有一個CSS無法實現的功能,就是尋找包含某個子項目的父元素.的確,目前的CSS還無法實現,不過在未來CSS4的選取器中,將會有一個父選取器

E! > F    //注意,2011年的時候,父選取器的文法是$E > F,今年草案又改了.網上有些介紹CSS4選取器的博文還是舊的,這裡有一個能在CSS檔案中使用父選取器的polyfill https://github.com/Idered/cssParentSelector

該選取器可以選取到那些包含子項目F的E元素.但即便以後實現了CSS4,稍微改變一下需求,尋找那些包含後代元素F的E元素,CSS選取器又怎麼寫呢?應該是沒什麼辦法實現.熟悉jQuery的朋友可能會說,jQuery裡有:has偽類,可以這麼寫E:has(F),的確,如果使用jQuery自訂的過濾器,幾乎任何需求都可以用遍曆DOM的方法實現,但效率絕對會很低.而XPath就不一樣了,畢竟Firefox和chrome都已經實現了XPath的介面document.evaluate方法(Wicked Good XPath應該主要是努力在IE上實現統一的介面),速度肯定比手動遍曆DOM來的快.XPath的寫法是這樣的//E[.//F],怎麼樣,也挺簡單明了的.

另外很重要的一點是,CSS本來是用於給HTML添加樣式的,12種節點類型中,只有元素節點(nodetype等於1)才有樣式這一說,因此,CSS選取器只能選取到頁面中的元素節點,而XPath就不是了,它不光可以用在HTML中,還可以用在XML中,除了元素節點,而可以選擇屬性節點(//@*)或者文本節點(//text())等,如果未來XPath2.0實現了,它會變的更加強大.

 

下文是對C#對XML的具體操作

如何完成.Net下XML文檔的讀寫操作

C#操作xml SelectNodes,SelectSingleNode總是返回NULL 與 xPath 介紹

C#中用SelectSingleNode方法解析帶有多個命名空間的XML檔案

原文地址

黃聰:C#操作xml SelectNodes,SelectSingleNode通過 xPath 定位class包含Contains的DIV

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.