美文网首页
C#中使用XPath示例总结

C#中使用XPath示例总结

作者: Sunday_1024 | 来源:发表于2021-03-17 12:23 被阅读0次

    0 xpath简介

    用来解析html或xml查找信息的语言。

    1 xpath语法

    表达式 描述
    nodename 选取此节点的所有子节点。
    / 从根节点选取。
    // 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
    . 选取当前节点。
    .. 选取当前节点的父节点。
    @ 选取属性。
    例子

    以下面的这个xml为例子

    <?xml version="1.0" encoding="ISO-8859-1"?>
    
    <bookstore>
    
    <book>
      <title lang="eng">Harry Potter</title>
      <price>29.99</price>
    </book>
    
    <book>
      <title lang="eng">Learning XML</title>
      <price>39.95</price>
    </book>
    
    </bookstore>
    
    • xml.xpath(“bookstore”) 表示选取 bookstore 元素的所有子节点
    • xml.xpath(“/bookstore”) 表示选取根元素 bookstore。
    • xml.xpath(“bookstore/book”) 选取属于 bookstore 的子元素的所有 book 元素。
    • xml.xpath(“//book”) 选取所有 book 子元素,而不管它们在文档中的位置。
    • xml.xpath(“bookstore//book”) 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
    • xml.xpath(“//@lang”) 选取名为 lang 的所有属性。
    谓语
    路径表达式 结果
    /bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。
    /bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。
    /bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
    /bookstore/book[position()<3] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
    //title[@lang] 选取所有拥有名为 lang 的属性的 title 元素。
    //title[@lang=’eng’] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
    /bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
    /bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。
    选取未知节点
    通配符 描述
    * 匹配任何元素节点。
    @* 匹配任何属性节点。
    node() 匹配任何类型的节点。

    例子:

    路径表达式 结果
    /bookstore/* 选取 bookstore 元素的所有子元素。
    //* 选取文档中的所有元素。
    //title[@*] 选取所有带有属性的 title 元素。
    选取若干路径

    通过在路径表达式中使用“|”运算符,您可以选取若干个路径。

    • //book/title | //book/price 选取 book 元素的所有 title 和 price 元素。
    • //title | //price 选取文档中的所有 title 和 price 元素。
    • /bookstore/book/title | //price 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。

    2 轴

    轴可定义相对于当前节点的节点集。

    轴名称 结果
    ancestor 选取当前节点的所有先辈(父、祖父等)。
    ancestor-or-self 选取当前节点的所有先辈(父、祖父等)以及当前节点本身。
    attribute 选取当前节点的所有属性。
    child 选取当前节点的所有子元素。
    descendant 选取当前节点的所有后代元素(子、孙等)。
    descendant-or-self 选取当前节点的所有后代元素(子、孙等)以及当前节点本身。
    following 选取文档中当前节点的结束标签之后的所有节点。
    namespace 选取当前节点的所有命名空间节点。
    parent 选取当前节点的父节点。
    preceding 选取文档中当前节点的开始标签之前的所有节点。
    preceding-sibling 选取当前节点之前的所有同级节点。
    self 选取当前节点。
    步的语法:

    轴名称::节点测试[谓语]

    例子:

    例子 结果
    child::book 选取所有属于当前节点的子元素的 book 节点。
    attribute::lang 选取当前节点的 lang 属性。
    child::* 选取当前节点的所有子元素。
    attribute::* 选取当前节点的所有属性。
    child::text() 选取当前节点的所有文本子节点。
    child::node() 选取当前节点的所有子节点。
    descendant::book 选取当前节点的所有 book 后代。
    ancestor::book 选择当前节点的所有 book 先辈。
    ancestor-or-self::book 选取当前节点的所有 book 先辈以及当前节点(如果此节点是 book 节点)
    child::*/child::price 选取当前节点的所有 price 孙节点。

    3 一些函数

      1. starts-with函数
        获取以xxx开头的元素
        例子:xpath(‘//div[stars-with(@class,”test”)]’)
      1. contains函数
        获取包含xxx的元素
        例子:xpath(‘//div[contains(@id,”test”)]’)
      1. not() 函数
        //选择不包含class属性的节点
        xpath("//span[not(@class)]");
        //选择不包含class和id属性的节点
        xpath("//span[not(@class) and not(@id)]");
        //选择不包含class="expire"的span
        xpath("//span[not(contains(@class,'expire'))]");
      1. and
        与的关系
        例子:xpath(‘//div[contains(@id,”test”) and contains(@id,"title")]’)
      1. text()函数
        获取内容文本
        例子1:xpath(‘//div[contains(text(),"test")]’)
        例子2:xpath(‘//div[@id="test"]/text()’)
        例子3:xpath("//div[@class='class3'][contains(text(),'div2')]/../text()")
      1. comment() 函数
        获取注释内容
        例子1:xpath(‘//comment()’)
      1. translate() 函数
        translate() 意为转换,经常用于忽略大小写

    比如说,想获取网站描述的内容值 <meta name='Description' content='友情链接查询' /> 或<meta name='description' content='友情链接查询' /> ,下面的xpath即可。

    //meta[translate(@name,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')="DESCRIPTION"]
    代码意思为:把name的值a到z转换为大写A到Z,判断是否和目标值"DESCRIPTION"(注意目标值是大写的)相等

    4 一个xpath示例(使用HtmlAgilityPack)

                    HtmlDocument doc = new HtmlDocument();
                    doc.LoadHtml(@"
    <html>
      <head>
        <meta name='content-type' content='text/html; charset=utf-8' />
        <title>友情链接查询 - 站长工具</title>
        <!-- uRj0Ak8VLEPhjWhg3m9z4EjXJwc -->
        <meta name='Keywords' content='友情链接查询' />
        <meta name='Description' content='友情链接查询' />
    
      </head>
      <body>
        <h1 class='heading'>Top News</h1>
        <p style='font-size: 200%'>World News only on this page</p>
        Ah, and here's some more text, by the way.
        <p>... and this is a parsed fragment ...</p>
    
        <a href='http://www.cydf.org.cn/' rel='nofollow' target='_blank'>青少年发展基金会</a> 
        <a href='http://www.4399.com/flash/32979.htm' target='_blank'>洛克王国</a> 
        <a href='http://www.4399.com/flash/35538.htm' target='_blank'>奥拉星</a> 
        <a href='http://game.3533.com/game/' target='_blank'>手机游戏</a>
        <a href='http://game.3533.com/tupian/' target='_blank'>手机壁纸</a>
        <a href='http://www.4399.com/' target='_blank'>4399小游戏</a> 
        <a href='http://www.91wan.com/' target='_blank'>91wan游戏</a>
    
      </body>
    </html>
    
    ");
    
                    HtmlNodeCollection nodes = doc.DocumentNode.SelectNodes("//a");//xpath表达式,获取所有链接
    
                    if (nodes == null)
                    {
                        txa_new.Text = "===================匹配不到==================";
                        return;
                    }
    
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine("获取匹配节点(node)总数:" + nodes.Count);
                    sb.AppendLine("*******************我是分隔符*******************");
    
                    HtmlNode node;
    
                    for (int i = 0; i < nodes.Count; i++)
                    {
                        node = nodes[i];
                        if (cb_showAttributes.Checked)
                        {
                            var attrList = node.Attributes;
                            foreach (var attr in attrList)
                            {
                                sb.AppendLine("[Attributes]:" + attr.Name + " => " + attr.Value);
                            }
                        }
                        if(cb_InnerHtml.Checked)sb.AppendLine("[InnerHtml]:" + node.InnerHtml);
                        if(cb_InnerText.Checked)sb.AppendLine("[InnerText]:" + node.InnerText);
                        if(cb_OuterHtml.Checked)sb.AppendLine("[OuterHtml]:" + node.OuterHtml);
                        if(cb_XPath.Checked)    sb.AppendLine("[XPath]:"     + node.XPath);
                        sb.AppendLine(string.Format("===================我是分隔符{0}===================",i+1));
                    }
    
    
                    txa_new.Text = sb.ToString();
    

    获取结果:

    获取匹配节点(node)总数:7
    *******************我是分隔符*******************
    [Attributes]:href => http://www.cydf.org.cn/
    [Attributes]:rel => nofollow
    [Attributes]:target => _blank
    [InnerHtml]:青少年发展基金会
    [InnerText]:青少年发展基金会
    [OuterHtml]:<a href="http://www.cydf.org.cn/" rel="nofollow" target="_blank">青少年发展基金会</a>
    [XPath]:/html[1]/body[1]/a[1]
    ===================我是分隔符1===================
    [Attributes]:href => http://www.4399.com/flash/32979.htm
    [Attributes]:target => _blank
    [InnerHtml]:洛克王国
    [InnerText]:洛克王国
    [OuterHtml]:<a href="http://www.4399.com/flash/32979.htm" target="_blank">洛克王国</a>
    [XPath]:/html[1]/body[1]/a[2]
    ===================我是分隔符2===================
    [Attributes]:href => http://www.4399.com/flash/35538.htm
    [Attributes]:target => _blank
    [InnerHtml]:奥拉星
    [InnerText]:奥拉星
    [OuterHtml]:<a href="http://www.4399.com/flash/35538.htm" target="_blank">奥拉星</a>
    [XPath]:/html[1]/body[1]/a[3]
    ===================我是分隔符3===================
    [Attributes]:href => http://game.3533.com/game/
    [Attributes]:target => _blank
    [InnerHtml]:手机游戏
    [InnerText]:手机游戏
    [OuterHtml]:<a href="http://game.3533.com/game/" target="_blank">手机游戏</a>
    [XPath]:/html[1]/body[1]/a[4]
    ===================我是分隔符4===================
    [Attributes]:href => http://game.3533.com/tupian/
    [Attributes]:target => _blank
    [InnerHtml]:手机壁纸
    [InnerText]:手机壁纸
    [OuterHtml]:<a href="http://game.3533.com/tupian/" target="_blank">手机壁纸</a>
    [XPath]:/html[1]/body[1]/a[5]
    ===================我是分隔符5===================
    [Attributes]:href => http://www.4399.com/
    [Attributes]:target => _blank
    [InnerHtml]:4399小游戏
    [InnerText]:4399小游戏
    [OuterHtml]:<a href="http://www.4399.com/" target="_blank">4399小游戏</a>
    [XPath]:/html[1]/body[1]/a[6]
    ===================我是分隔符6===================
    [Attributes]:href => http://www.91wan.com/
    [Attributes]:target => _blank
    [InnerHtml]:91wan游戏
    [InnerText]:91wan游戏
    [OuterHtml]:<a href="http://www.91wan.com/" target="_blank">91wan游戏</a>
    [XPath]:/html[1]/body[1]/a[7]
    ===================我是分隔符7===================
    
    

    删除注释内容

                HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
                doc.LoadHtml(html或xml的code);
    
                foreach (HtmlNode comment in doc.DocumentNode.SelectNodes("//comment()"))
                {
                    //删除注释的html或xml代码
                    comment.ParentNode.RemoveChild(comment);
                }
                //获取删除注释后的html或xml代码
                string newHtml = doc.DocumentNode.InnerHtml;
    

    5 注意一点

    xpath只能是小写(跟数据大小写无关),否则不能正常匹配你要查的数据。
    测试xpath可以使用工具: http://www.1024todo.cn:8000/tool.aspx#/tool/xpath.aspx

    相关文章

      网友评论

          本文标题:C#中使用XPath示例总结

          本文链接:https://www.haomeiwen.com/subject/ibwscltx.html