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


一. SelectNodes,SelectSingleNode總是返回NULL

   下面以一個簡單的xml為例:

<?xml version="1.0"?> <message xmlns="http://www.mydomain.com/MyDataFeed" xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance 
xsi:schemaLocation="http://www.mydomain.com/MyDataFeed https://secure.mydomain/MyDataFeed/myDataFeed.xsd" 
requestId="13898" status="1"> <error>Invalid Login</error> </message>

     下面嘗試讀取error節點的內容

XmlNode errorNode = xmldoc.SelectSingleNode("/message/error"); if (errorNode != null) Console.Writeline("There is an error");

     返回的結果一直為Null

     產生這個問題的原因就在於上面的xml文檔中使用了命名空間,當xml中定義了命名空間時,在查找節點的時候需要使用下面的方法

XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmldoc.NameTable); nsMgr.AddNamespace("ns", "http://www.mydomain.com/MyDataFeed");
XmlNode errorNode = xmldoc.SelectSingleNode("/ns:message/ns:error", nsMgr);

    如果直接想定位到error,而不是從根開始,需要寫為

xmldoc.SelectSingleNode("//ns:error", nsMgr); 

    感謝: http://stackoverflow.com/questions/1766254/selectsinglenode-always-returns-null

二 1. xPath介紹

   下面這個文章轉載的太多了,已經不知道出處了…

XPath 是XML的查詢語言,和SQL的角色很類似。以下面XML為例,介紹XPath 的語法。

<?xml version="1.0" encoding="ISO-8859-1"?>     

<catalog>     

  <cd country="USA">     

    <title>Empire Burlesque</title>     

    <artist>Bob Dylan</artist>     

    <price>10.90</price>    

  </cd>     

  <cd country="UK">     

    <title>Hide your heart</title>   

     <artist>Bonnie Tyler</artist>   

     <price>9.90</price>     

  </cd>     

  <cd country="USA">    

    <title>Greatest Hits</title>   

     <artist>Dolly Parton</artist>    

    <price>9.90</price>    

  </cd>   

</catalog>

定位節點

XML是樹狀結構,類似檔案系統內數據夾的結構,XPath也類似檔案系統的路徑命名方式。不過XPath 是一種模式(Pattern),可以選出 XML檔案中,路徑符合某個模式的所有節點出來。例如要選catalog底下的cd中所有price元素可以用:

/catalog/cd/price

如果XPath的開頭是一個斜線(/)代表這是絕對路徑。如果開頭是兩個斜線(//)表示文件中所有符合模式的元素都會被選出來,即使是處於樹中不同的層級也會被選出來。以下的語法會選出文件中所有叫做cd的元素(在樹中的任何層級都會被選出來):

//cd

選擇未知的元素

使用星號(Wildcards,*)可以選擇未知的元素。下面這個語法會選出/catalog/cd 的所有子元素:

/catalog/cdprice

以下的語法會選出有兩層父節點,叫做price的所有元素。

price

以下的語法會選擇出文件中的所有元素。

//*

要注意的是,想要存取不分層級的元素,XPath語法必須以兩個斜線開頭(//),想要存取未知元素才用星號(*),星號只能代表未知名稱的元素,不能代表未知層級的元素。

選擇分支

使用中括號可以選擇分支。以下的語法從catalog的子元素中取出第一個叫做cd的元素。XPath的定義中沒有第0元素這種東西。

/catalog/cd[1]

以下語法選擇catalog中的最后一個cd元素:(XPathj並沒有定義 first() 這種函式喔,用上例的 [1]就可以取出第一個元素。

/catalog/cd[last()]

以下語法選出含有price子元素的所有/catalog/cd元素。

/catalog/cd[price]

以下語法選出price元素的值等於10.90的所有/catalog/cd元素

/catalog/cd[price=10.90]

以下語法選出price元素的值等於10.90的所有/catalog/cd元素 的price元素

/catalog/cd[price=10.90]/price

選擇一個以上的路徑

使用Or操作數(|)就可以選擇一個以上的路徑。例如:

/catalog/cd/title | catalog/cd/artist

選擇所有title以及artist元素

//title | //artist

選擇所有title以及artist以及price元素

//title | //artist | //price

選擇屬性

在XPath中,除了選擇元素以外,也可以選擇屬性。屬性都是以@開頭。例如選擇文件中所有叫做country的屬性:

//@country

選擇所有含有country這個屬性的cd元素:

//cd[@country]

以下語法選擇出含有屬性的所有cd元素

//cd[@*]

以下語法選擇出country屬性值為UK的cd元素

//cd[@country='UK']

只要掌握了xpath語法,理論上你就可以訪問xml文件中的任意節點和任意值

XmlNode xmlnode = xmldoc.SelectSingleNode("//document/section[@id='pla-01']/data[@id='fou_scc_code']");

 

 

 

 

2、[譯]XPath和CSS選擇器

原文: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的支持.剛好,谷歌在上個月發布了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); //傳給jQuery工廠方法,返回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文件

原文地址


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM