some things

////html[1]/body[1]/div[9]/div[1]/div[1]/div[1]/ul/li  截取規則
Articles/Article[1]:選取屬於Articles子元素的第一個Article元素。 

/Articles/Article[last()]:選取屬於Articles子元素的最後一個Article元素。 
/Articles/Article[last()-1]:選取屬於Articles子元素的倒數第二個Article元素。 
/Articles/Article[position()<3]:選取最前面的兩個屬於 bookstore 元素的子元素的Article元素。 
//title[@lang]:選取全部擁有名爲lang的屬性的title元素。 
//CreateAt[@type='zh-cn']:選取全部CreateAt元素,且這些元素擁有值爲zh-cn的type屬性。 
/Articles/Article[Order>2]:選取Articles元素的全部Article元素,且其中的Order元素的值須大於2。 
/Articles/Article[Order<3]/Title:選取Articles元素中的Article元素的全部Title元素,且其中的Order元素的值須小於3。
javascript

剛剛學習了XPath路徑表達式,主要是對XML文檔中的節點進行搜索,經過XPath表達式能夠對XML文檔中的節點位置進行快速定位和訪問,html也是也是一種相似於xml的標記語言,可是語法沒有那麼嚴謹,在codeplex裏有一個開源項目HtmlAgilityPack提供了用XPath解析HTML文件,下面掩飾如何使用該類庫的使用
css

首先說下XPath路徑表達式html

XPath路徑表達式java

  用來選取XML文檔中的節點或節點集的node

  一、術語:節點(Node):7種類型:元素,屬性,文本,命名空間,處理命令,註釋,文檔(根)節點app

  二、節點關係:父(Parent),子(Children),同胞(Sibling),先輩(Ancestor),後代(Descendant)函數

  三、路徑表達式post

   nodename  節點名,選取此節點的全部子節點  例: childnode  當前節點中的childnode子節點,不包含孫子及如下的節點學習

      /     從根節點選取  例:/root/childnode/grandsonnode  測試

       //     表示全部後代節點  例://childnode    全部名爲childnode的後代節點

      .    表示當前節點  例:  ./childnode    表示當前節點的childnode節點

      ..     表示父節點  例:  ../nearnode     表示父親節點的nearnode子節點

       @    選取屬性  /root/childnode/@id     表示childnode的全部含有id屬性的節點集

  四、謂語(Predicates)

    謂語能夠對節點集進行一些限制,使選擇更精確

      /root/book[1]    節點集中的第一個節點

      /root/book[last()]  節點集中最後一個節點

      /root/book[position() - 1]  節點集中倒數第二個節點集

      /root/book[position() < 5]  節點集中前五個節點集

      /root/book[@id]      節點集中含有屬性id的節點集

      /root/book[@id='chinese']  節點集中id屬性值爲chinese的節點集

      /root/book[price > 35]/title  節點集中book的price元素值大於35的title節點集

  五、通配符:XPath路徑中一樣支持通配符(*,@*,node(), text())

    例:  /bookstore/*

        //title[@*]

  六、XPath軸

    定義相對於當前節點的節點集

      ancestor    全部祖先節點

//刪除註釋,script,style
    node.Descendants()
                .Where(n => n.Name == "script" || n.Name == "style" || n.Name=="#comment")
                .ToList().ForEach(n => n.Remove());


    //遍歷node節點的全部後代節點
    foreach(var HtmlNode in node.Descendants())
    {
        
    }

 

      attribute    全部屬性節點

      child      全部子元素

      descendant  全部後代節點(子,孫。。。)

      following    結束標記後的全部節點      preceding   開始標記前的全部節點

      following-sibling  結束標記後的全部同胞節點

      preceding-sibling  開始標記前的全部同胞節點

      namespace   當前命名空間的全部節點

      parent     父節點

      self       當前節點

    用法:軸名稱::節點測試[謂語]

      例:  ancestor::book

            child::text()

  七、運算符

    |  兩個節點集的合併  例:/root/book[1] | /root/book[3]

    +,-,*,dev,mod

    =,!=,<,>,<=,>=

    or,and  或和與

 

補充:

  多個屬性條件查詢      //div[@align='center' and @height='24']

  不存在class屬性       //div[not(@class)]

static void Main(string[] args)
        {
            //<ul class="user_match clear">
            //    <li>年齡:21~30之間</li>
            //    <li>婚史:未婚</li>
            //    <li>地區:不限</li>
            //    <li>身高:175~185釐米之間</li>
            //    <li>學歷:不限</li>
            //    <li>職業:不限</li>
            //    <li>月薪:不限</li>
            //    <li>住房:不限</li>
            //    <li>購車:不限</li>
            //</ul>


            WebClient wc = new WebClient();
            wc.BaseAddress = "http://www.juedui100.com/";
            wc.Encoding = Encoding.UTF8;
            HtmlDocument doc = new HtmlDocument();
            string html = wc.DownloadString("user/6971070.html");
            doc.LoadHtml(html);
            HtmlNode node = doc.DocumentNode.SelectSingleNode("/html/body/div[4]/div[1]/div[2]/ul[1]");     //根據XPath查找節點,跟XmlNode差很少

            IEnumerable<HtmlNode> nodeList = node.Ancestors();  //獲取該元素全部的父節點的集合
            foreach (HtmlNode item in nodeList)
            {
                Console.Write(item.Name + " ");   //輸出 div div body html #document
            }
            Console.WriteLine();

            IEnumerable<HtmlNode> nodeList1 = node.Ancestors("body");  //獲取名字匹配的該元素的父集合,其實參數就是一個篩選的功能
            foreach (HtmlNode item in nodeList1)
            {
                Console.Write(item.Name + " ");   //輸出 body
            }
            Console.WriteLine();

            IEnumerable<HtmlNode> nodeList2 = node.AncestorsAndSelf();  //獲取全部的父節點和自身
            foreach (HtmlNode item in nodeList2)
            {
                Console.Write(item.Name + " "); //輸出 ul div div div body html #document
            }
            Console.WriteLine();

            IEnumerable<HtmlNode> nodeList3 = node.AncestorsAndSelf("div");     //獲取父節點和自身,參數用於篩選
            foreach (HtmlNode item in nodeList3)
            {
                Console.Write(item.Name + " "); //輸出 div div div
            }
            Console.WriteLine();

            HtmlNode node1 = doc.CreateElement("li");
            node1.InnerHtml = "我是附加的li元素";
            node.AppendChild(node1);    //...<li>購車:不限</li> 後面加了一個<li>我是附加的li元素</li>
            Console.WriteLine(node.InnerHtml);


            HtmlNode node2 = doc.CreateElement("li");
            node2.InnerHtml = "新li一";
            HtmlNode node3 = doc.CreateElement("li");
            node3.InnerHtml = "新li二";
            HtmlNodeCollection nc = new HtmlNodeCollection(node2);
            nc.Add(node2);
            nc.Add(node3);
            node.AppendChildren(nc);    //一次過追加多個元素
            Console.WriteLine(node.InnerHtml);      //...<li>我是附加的li元素</li><li>新li一</li><li>新li二</li>

            Console.WriteLine(HtmlNode.CanOverlapElement("node2"));     //輸出False   肯定是否能夠保存一個重複的元素

            IEnumerable<HtmlAttribute> attrs = node.ChildAttributes("class");   //獲取子節點與自身的全部名爲class的屬性集合
            foreach (HtmlAttribute attr in attrs)
            {
                Console.Write(attr.Value);      //輸出 user_match clear 
            }

            HtmlNode node4 = node.Clone();
            Console.WriteLine(node4.InnerHtml);     //輸出node的代碼,node已被複制到了node

            HtmlNode node5 = node.CloneNode(false); //參數決定是否複製子節點,與XmlNode同樣
            Console.WriteLine(node5.OuterHtml);     //<ul class="user_match clear"></ul>    由於參數設爲了false子節點沒有被複制

            HtmlNode node6 = node.CloneNode("div");    //複製節點的同時,更更名字
            Console.WriteLine(node6.OuterHtml);        //輸出 <div class="user_match clear"><li>年齡:21~30之間</li>...</div>  ul已被改成了div

            HtmlNode node7 = node.CloneNode("table",false);
            Console.WriteLine(node7.OuterHtml);        //輸出<table class="user_match clear"></table>     參數爲false因此沒有複製子節點

            HtmlNode node8 = node.SelectSingleNode("child::li[1]");
            node.CopyFrom(node);
            Console.WriteLine(node.OuterHtml);
            Console.WriteLine("========================");
            //public void CopyFrom(HtmlNode node);
            //public void CopyFrom(HtmlNode node, bool deep);
            //public XPathNavigator CreateNavigator();
            //public XPathNavigator CreateRootNavigator();

            HtmlNode node9 = HtmlNode.CreateNode("<li>新節點</li>");   //直接用字符串建立節點,仍是挺好用的
            Console.WriteLine(node9.OuterHtml);     //輸出 <li>新節點</li>

            IEnumerable<HtmlNode> nodeList4 = node.DescendantNodes();   //獲取全部的子節點集合
            foreach (HtmlNode item in nodeList4)
            {
                Console.Write(item.OuterHtml);      //輸出 node的每一個子li節點
            }
            Console.WriteLine("===================");

            IEnumerable<HtmlNode> nodeList5 = node.DescendantNodesAndSelf();
            foreach (HtmlNode item in nodeList5)
            {
                Console.Write(item.OuterHtml);      //輸出自身<ul>..包括子節點<li>...</li></ul> 再輸出全部的子li節點
            }
            Console.WriteLine();

            IEnumerable<HtmlNode> nodeList6 = node.DescendantNodes();   //獲取枚舉列表中的全部子代節
            foreach (HtmlNode item in nodeList6)
            {
                Console.Write(item.InnerText);  //輸出全部的li節點的內容
            }
            Console.WriteLine("---------------");

            IEnumerable<HtmlNode> nodeList7 = node.Descendants("li");   //獲取全部的子後代元素    //文本節點不在此範圍內
            foreach(HtmlNode item in nodeList7)
            {
                Console.Write(item.InnerText);   
            }

            IEnumerable<HtmlNode> nodeList8 = node.DescendantsAndSelf("ul");   //獲取全部的子後代元素    //文本節點不在此範圍內
            foreach (HtmlNode item in nodeList8)
            {
                Console.Write(item.Name);       //輸出 ul 參數實際上只至關於過濾的做用
            }

            HtmlNode node10 = node.Element("li");   //獲取第一個子節點名稱匹配的元素
            Console.WriteLine(node10.InnerText);        //輸出 年齡:年齡:21~30之間
            Console.WriteLine("----------------------------------------");

            IEnumerable<HtmlNode> nodeList9 = node.Elements("li");
            foreach (HtmlNode item in nodeList9)
            {
                Console.Write(item.InnerText);      //輸出 全部的li節點內容
            }
            Console.WriteLine();

            //換一個新的,好像有點亂了
            HtmlNode newnode = doc.DocumentNode.SelectSingleNode("/html/body/div[4]/div[1]/div[3]");
            //<div class="col say">
            //    <h3>愛情獨白</h3>
            //    <p>願得一心人,白首不相離。我一直相信個人另外一半就在茫茫人海中,有一天必定會與我相遇。</p>
            //</div>

            //bool b = newnode.GetAttributeValue("class", false);   //獲取一個布爾值的屬性,沒有找到則返回第二個參數的默認值
            //Console.WriteLine(b);
            //int i = newnode.GetAttributeValue("class", 0);        //獲取一個整形的屬性,沒有找到則返回第二個參數的默認值
            //Console.WriteLine(i);

            string str = newnode.GetAttributeValue("class", "");    //獲取一個字符串屬性
            Console.WriteLine(str); //輸出 col say

            HtmlNode node11 = HtmlNode.CreateNode("<b>我是加粗節點</b>");
            HtmlNode node12 = newnode.SelectSingleNode("h3");
            newnode.InsertAfter(node11, node12);    //意思是在node12表明的h3節點後面插入node11節點
            Console.WriteLine(newnode.InnerHtml);   //h3>愛情獨白</h3><b>我是加粗節點</b><p>願得一心人...      留意到b節點已經被插入到h3後面

            newnode.InsertBefore(node11, node12);   //再插入多一次,方法不一樣罷了,此次是在node12帶包的h3前面插入
            Console.WriteLine(newnode.InnerHtml);   //<b>我是加粗節點</b><h3>愛情獨白</h3><b>我是加粗節點</b><p>願得一心人

            Console.WriteLine("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
            newnode.RemoveChild(node11);    //移除了第一個<b>我是加粗節點</b>   此方法的重載,第二個參數決定是否移除孫子節點
            Console.WriteLine(newnode.InnerHtml);   //<h3>愛情獨白</h3><b>我是加粗節點</b><p>願得一心人....

            newnode.RemoveAllChildren();        //移除全部子節點
            Console.WriteLine(newnode.OuterHtml);   //<div class="col say"></div>   全部子節點都被移除了

            newnode.RemoveAll();                    //移除全部的屬性和子節點,因爲子節點已經被上個方法移除了,所以此次連屬性也移除了
            Console.WriteLine(newnode.OuterHtml);   //輸出 <div></div>    注意到屬性也被移除了。

            //都移除光了,再來一個,仍是剛纔那個
            HtmlNode newnode1 = doc.DocumentNode.SelectSingleNode("/html/body/div[4]/div[1]/div[3]");
            Console.WriteLine("===================");
            Console.WriteLine(newnode1.OuterHtml);  //輸出 <div></div>    注意 移除是從HtmlDocument中移除的,再次獲取獲取不到了

            HtmlNode newnode2 = doc.DocumentNode.SelectSingleNode("/html/body/div[4]/div[1]/div[2]/div[2]/p");
            Console.WriteLine(newnode2.OuterHtml);
            //<p class="no_tip">她尚未設置不能忍受清單 
            //    <a href="javascript:invite(5971070,8,'邀請設置不能忍受');" class="link_b needlogin">邀請她設置</a>
            //</p>
            newnode2.Remove();    //從文檔樹中移除newnode2節點
            HtmlNode newnode3 = doc.DocumentNode.SelectSingleNode("/html/body/div[4]/div[1]/div[2]/div[2]/p");   //再次獲取該節點
            //Console.WriteLine(newnode3.OuterHtml);  //報未將對象引用到對象的實例異常,明顯是找不到了,

            HtmlNode newnode4 = doc.DocumentNode.SelectSingleNode("/html/body/div[4]/div[1]/div[1]/div/div[1]/p[2]/b[1]");
            Console.WriteLine(newnode4.OuterHtml);
            //<b>相冊:
            //    <a href="/photo/6971070.html" class="red">4</a>張
            //</b>
            HtmlNode node17 = HtmlNode.CreateNode("<div>再次建立一個節點</div>");
            newnode4.PrependChild(node17);      //跟AppengChild相似,只是插入位置不一樣PrependChildren接受一個節點集合,一次過插入多個節點而已
            Console.WriteLine(newnode4.OuterHtml);  
            //輸出
            //<b>相冊:
            //    <div>再次建立一個節點</div>
            //    <a href="/photo/6971070.html" class="red">4</a>張
            //</b>
            HtmlNode node16 = newnode4.SelectSingleNode("child::a[1]");
            HtmlNode node18 = HtmlNode.CreateNode("<p>新建一行</p>");
            newnode4.ReplaceChild(node18, node16);
            Console.WriteLine(newnode4.OuterHtml);
            //輸出
            //<b>相冊:
            //    <div>再次建立一個節點</div>
            //    <p>新建一行</p>張      //留意到node16表明得節點已經被替換掉了
            //</b>

            HtmlNode node19 = newnode4.SelectSingleNode("child::p[1]");
            node19.SetAttributeValue("class","class1");
            Console.WriteLine(node19.OuterHtml);    //輸出 <p class="class1">新建一行</p>

            Console.WriteLine(HtmlNode.IsOverlappedClosingElement("<a>我愛你</a>"));   //輸出 False
            Console.WriteLine(HtmlNode.IsCDataElement("<a>我愛你</a>"));   //輸出 False
            Console.WriteLine(HtmlNode.IsClosedElement("<a>我愛你</a>"));   //輸出 False
            Console.WriteLine(HtmlNode.IsEmptyElement("<a>我愛你</a>"));   //輸出 False
            Console.WriteLine(newnode4.OuterHtml);


            HtmlNode node20 = HtmlNode.CreateNode("<p>新的第二行</p>");
            newnode4.AppendChild(node20);
            HtmlNodeCollection hnc = newnode4.SelectNodes("//p");   //根據XPath一次過獲取多個Node
            Console.WriteLine(hnc.Count);   //輸出29

            string str1 = node20.WriteContentTo();
            Console.WriteLine(str1);    //輸出 新的第二行  將節點內容寫入字符串

            //public void WriteContentTo(TextWriter outText);
            //public string WriteTo();
            //public void WriteTo(TextWriter outText);
            //public void WriteTo(XmlWriter writer);
            Console.ReadKey();
        }

 

 

var divs = html.CssSelect("div");  //all div elements

var nodes = html.CssSelect("div.content"); //all div elements with css class ‘content’

var nodes = html.CssSelect("div.widget.monthlist"); //all div elements with the both css class

var nodes = html.CssSelect("#postPaging"); //all HTML elements with the id postPaging

var nodes = html.CssSelect("div#postPaging.testClass"); // all HTML elements with the id postPaging and css class testClass 

var nodes = html.CssSelect("div.content > p.para"); //p elements who are direct children of div elements with css class ‘content’ 

var nodes = html.CssSelect("input[type=text].login"); // textbox with css class login 

We can also select ancestors of elements:

var nodes = html.CssSelect("p.para").CssSelectAncestors("div.content > div.widget");

 

經常使用函數

xpath的經常使用函數主要包含節點集函數,字符串函數,布爾函數,數字函數,網上的資料較多,在此就再也不累述,可參考如下資料:

[a] XPath, XQuery, and XSLT Functions http://www.w3schools.com/xpath/xpath_functions.asp

[b] XPath Functions http://www.caucho.com/resin-3.0/xml/xpath-fun.xtp

[c] XPath Functions(MSDN) http://msdn2.microsoft.com/en-us/library/ms256138.aspx

經常使用定位語句實例

1. //NODE[not(@class)] 全部節點名爲node,且不包含class屬性的節點

2. //NODE[@class and @id] 全部節點名爲node,且同時包含class屬性和id屬性的節點

3. //NODE[contains(text(),substring] 全部節點名爲node,且其文本中包含substring的節點

//A[contains(text(),\"下一頁\")] 全部包含「下一頁」字符串的超連接節點

//A[contains(@title,"文章標題")] 全部其title屬性中包含「文章標題」字符串的超連接節點

4. //NODE[@id="myid"]/text() 節點名爲node,且屬性id爲myid的節點的全部直接text子節點

5. BOOK[author/degree] 全部包含author節點同時該author節點至少含有一個的degree孩子節點的book節點

6. AUTHOR[.="Matthew Bob"] 全部值爲「Matthew Bob」的author節點

7. //*[count(BBB)=2] 全部包含兩個BBB孩子節點的節點

8. //*[count(*)=2] 全部包含兩個孩子節點的節點

9. //*[name()='BBB'] 全部名字爲BBB的節點,等同於//BBB

10. //*[starts-with(name(),'B')] 全部名字開頭爲字母B的節點

11. //*[contains(name(),'C')] 全部名字中包含字母C的節點

12. //*[string-length(name()) = 3] 名字長度爲3個字母的節點

13. //CCC | //BBB 全部CCC節點或BBB節點

14. /child::AAA 等價於/AAA

15. //CCC/descendant::* 全部以CCC爲其祖先的節點

16. //DDD/parent::* DDD節點的全部父節點

17. //BBB[position() mod 2 = 0] 偶數位置的BBB節點

18. AUTHOR[not(last-name = "Bob")] 全部不包含元素last-name的值爲Bob的節點

19. P/text()[2] 當前上下文節點中的P節點的第二個文本節點

20. ancestor::BOOK[1] 離當前上下文節點最近的book祖先節點

21. //A[text()="next"] 錨文本內容等於next的A節點

 

 

最後推薦一款在Firefox中用的XPath插件:

XPath Checker

https://addons.mozilla.org/en-US/firefox/addon/1095

這個插件能夠方便查看網頁中任意元素的XPath路徑,但其自動生成的XPath路徑一般不是最簡路徑。

 

參考資料

[1]XPath Examples. http://msdn2.microsoft.com/en-us/library/ms256086.aspx

[2]XPath Tutorial http://www.zvon.org/xxl/XPathTutorial/Output/example1.html

[3]XPath介紹 http://www.xml.org.cn/dispbbs.asp?boardID=14&ID=35493

[4]XPath reference http://msdn2.microsoft.com/en-us/library/ms256115.aspx

[5]XML Path Language (XPath)Version 1.0 http://www.w3.org/TR/xpath

[6]XPath Tutorial http://www.w3schools.com/xpath/default.asp

相關文章
相關標籤/搜索