【问题标题】:HtmlAgilityPack get two nodes simultaneously in c#HtmlAgilityPack 在 c# 中同时获取两个节点
【发布时间】:2016-03-03 13:12:01
【问题描述】:

我正在尝试解析一个 html 页面, 我会从这段代码中得到一对节点

 <li class="classli"> 
    <div class="element">element1</div>  
    <div class="description">description1</div> 
  </li>  
  <li class="classli"> 
    <div class="element">element2</div>  
    <div class="description">description2</div> 
  </li>  
  <li class="classli"> 
    <div class="xxxelementclass">element3</div>  
    <div class="description">description3</div> 
  </li>  
  <li class="classli"> 
    <div class="element">element4</div>  
    <div class="xxxclass">description4</div> 
  </li> 

我在 c# 中试过这个:

foreach(var node in doc.SelectNodes("//li[contains(@class,classli)]"))
{
    listelement.add(node.SelectSingleNode("//div[contains(@class,element)]").InnerText);
    listdescription(node.SelectSingleNode("//div[contains(@class,description)]").InnerText);
}

在 HTML 页面中,并非所有 (li) 标签都包含相同的子标签,我 只会在两者都存在的情况下获得描述和元素

【问题讨论】:

    标签: c# xpath html-agility-pack


    【解决方案1】:

    通过 CSS 类匹配的正确 XPath 表达式有点复杂。采取适度的方法,即在this other answer 中发布的第二个代码 sn-p,您的任务的 XPath 将如下(为了便于阅读而格式化为行):

    var query = @"//li[contains(concat(' ', @class, ' '), ' classli ')]
                      [div[contains(concat(' ', @class, ' '), ' element ')]]
                      [div[contains(concat(' ', @class, ' '), ' description ')]]";
    
    foreach(var node in doc.SelectNodes(query))
    {
        var elementQuery = "div[contains(concat(' ', @class, ' '), ' element ')]";
        listelement.add(node.SelectSingleNode(elementQuery).InnerText);
    
        var descriptionQuery = "div[contains(concat(' ', @class, ' '), ' description ')]";
        listdescription.add(node.SelectSingleNode(descriptionQuery).InnerText);
    }
    

    【讨论】:

      【解决方案2】:

      在你的 for each 中设置你的 xpath,如下所示

      //li[contains(@class,'classli') and ./div[contains(@class,'element')] and ./div[contains(@class,'description')]]
      

      这只会将具有给定类的两个 div 的元素视为子节点,还请注意,每个内部的 xpaths 都需要从 li 节点开始寻找后代节点,因此您需要使用 @987654322 @ 用于儿童或.// 用于后代,例如

      ./div[contains(@class,'element')]
      
      ./div[contains(@class,'description')]
      

      【讨论】:

        【解决方案3】:

        AsEnumerable谢谢大家的帮助 我是这样解决的

            foreach(var node in doc.SelectNodes("//li[contains(@class,classli)]"))
            {
        
           List<HTMLNODE> Child = node.childnodes.where(o=> (o.getattribbutevalue(class,"") == "element") or (o.getattribbutevalue(class,"") == "description")).AsEnumerable().ToList();
        
            }
        
        For(int i = 0; i <= Child.count-1;i=i+2)
        {
        listelement.add(Child[i].InnerHtml;
        listdescription.add(Child[i+1].InnerHtml;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多