2012-12-07 21 views
51

द्वारा सभी तत्व प्राप्त करें मैं एचटीएमएल चपलता पैक पर एक स्टैब ले रहा हूं और इसके बारे में जाने का सही तरीका ढूंढने में परेशानी है।एचटीएमएल एजिलिटी पैक कक्षा

उदाहरण के लिए:

var findclasses = _doc.DocumentNode.Descendants("div").Where(d => d.Attributes.Contains("class")); 

हालांकि, स्पष्ट रूप से आप कक्षाएं एक बहुत करने के लिए अधिक जोड़ सकते हैं तो divs तो मैं इस कोशिश की ..

var allLinksWithDivAndClass = _doc.DocumentNode.SelectNodes("//*[@class=\"float\"]"); 

लेकिन वह मामलों को संभाल नहीं करता है जहाँ आप कई वर्गों को जोड़ें और "फ्लोट" उनमें से केवल एक है ..

class="className float anotherclassName" 

क्या यह सब संभालने का कोई तरीका है? मैं मूल रूप से सभी नोड्स का चयन करना चाहता हूं जिनमें कक्षा = और फ्लोट शामिल है।

** जवाब में पूरे स्पष्टीकरण के साथ अपने ब्लॉग पर दर्ज किया गया है: Html Agility Pack Get All Elements by Class

उत्तर

79

बस अपने विधेय के लिए और अधिक शर्तें जोड़ें:

var findclasses = _doc.DocumentNode 
    .Descendants("div") 
    .Where(d => 
     d.Attributes.Contains("class") 
     && 
     d.Attributes["class"].Value.Contains("float") 
    ); 

मैं एक विस्तार विधि HasClass बनाने का सुझाव हो सकता है और इसका इस्तेमाल करते हैं जैसे इतना:

IEnumerable<HtmlNode> hasFloatClass = _doc.DocumentNode 
    .Descendants("div") 
    .Where(div => div.HasClass("float")); 

public static Boolean HasClass(this HtmlNode element, String className) 
{ 
    if(element == null) throw new ArgumentNullException(nameof(element)); 
    if(String.IsNullOrWhitespace(className)) throw new ArgumentNullException(nameof(className)); 
    if(element.NodeType != HtmlNodeType.Element) return false; 

    HtmlAttribute classAttrib = element.Attributes["class"]; 
    if(classAttrib == null) return false; 

    Boolean hasClass = CheapClassListContains(classAttrib.Value, className, StringComparison.Ordinal); 
    return hasClass; 
} 

/// <summary>Performs optionally-whitespace-padded string search without new string allocations.</summary> 
/// <remarks>A regex might also work, but constructing a new regex every time this method is called would be expensive.</remarks> 
private static Boolean CheapClassListContains(String haystack, String needle, StringComparison comparison) 
{ 
    if(String.Equals(haystack, needle, comparison)) return true; 
    Int32 idx = 0; 
    while(idx + needle.Length <= haystack.Length) 
    { 
     idx = haystack.IndexOf(needle, idx, comparison); 
     if(idx == -1) return false; 

     Int32 end = idx + needle.Length; 

     // Needle must be enclosed in whitespace or be at the start/end of string 
     Boolean validStart = idx == 0    || Char.IsWhiteSpace(haystack[idx - 1]); 
     Boolean validEnd = end == haystack.Length || Char.IsWhiteSpace(haystack[end]); 
     if(validStart && validEnd) return true; 

     idx++; 
    } 
    return false; 
} 

HtmlAgilityPack डोम इंटरफेस के एक कार्यान्वयन प्रदान करती है (उदाहरण के लिए createElement, getElementById, आदि) लेकिन यह अभी थोड़ा सा है और classList जैसी नई डोम सुविधाओं को याद कर रहा है जो यह मामूली बना देगा।

... शायद मैं नए बदलावों के साथ पैच अनुरोध सबमिट कर सकता हूं, लेकिन HtmlAgilityPack में कोई आधिकारिक गिटहब रेपो नहीं है।

+0

अभ्यस्त इस कारण केवल पाया जा सकता है divs? क्या होगा यदि मैं उस वर्ग को Adam

+1

फिर "div" predicate को हटा दें। – Dai

+0

क्या आप बस कर सकते हैं। डिसेन्डेंट्स ("")? – Adam

68

आप नीचे के रूप में, का उपयोग कर अपने XPath क्वेरी भीतर समारोह 'शामिल' करके अपनी समस्या का समाधान कर सकते हैं:

var allElementsWithClassFloat = 
    _doc.DocumentNode.SelectNodes("//*[contains(@class,'float')]") 

एक समारोह में यह पुन: उपयोग निम्न जैसा कुछ करने के लिए:

string classToFind = "float";  
var allElementsWithClassFloat = 
    _doc.DocumentNode.SelectNodes(string.Format("//*[contains(@class,'{0}')]", classToFind)); 
+0

ऑब्जेक्ट प्रकार 'allElementsWithClassFloat' क्या होगा? –

+0

'allElementsWithClassFloat' एक HtmlNodeCollection – feztheforeigner

+0

स्ट्रिंग के बजाय है। फर्मेट आप '$" // * [शामिल हैं (@class,' {classToFind} ')] "' – feztheforeigner

-7

आप निम्न स्क्रिप्ट का उपयोग कर सकते हैं:

var findclasses = _doc.DocumentNode.Descendants("div").Where(d => 
    d.Attributes.Contains("class") && d.Attributes["class"].Value.Contains("float") 
); 
2

मैंने इस प्रोजेक्ट विधि को मेरे प्रोजेक्ट में बहुत कुछ उपयोग किया। उम्मीद है कि यह आप में से किसी एक की मदद करेगा।

public static bool HasClass(this HtmlNode node, params string[] classValueArray) 
    { 
     var classValue = node.GetAttributeValue("class", ""); 
     var classValues = classValue.Split(' '); 
     return classValueArray.All(c => classValues.Contains(c)); 
    } 
+1

जब आप वास्तव में चाहते हैं तो 'ToLower()' का उपयोग न करें IgnoreCase तुलना करना है। 'स्ट्रिंग कॉम्परिसन। कल्चर इग्नोरकेस' पास करना क्लीनर है और एक और स्पष्ट इरादा दिखाता है। –

+0

हाँ आप सही हैं। हम निश्चित रूप से इसका उपयोग कर सकते हैं। –

0
public static List<HtmlNode> GetTagsWithClass(string html,List<string> @class) 
    { 
     // LoadHtml(html);   
     var result = htmlDocument.DocumentNode.Descendants() 
      .Where(x =>x.Attributes.Contains("class") && @class.Contains(x.Attributes["class"].Value)).ToList();   
     return result; 
    }  
संबंधित मुद्दे