2012-01-20 10 views
5

के साथ पार्सिंग डीएल यह नमूना HTML है I ASP.Net (C#) में एचटीएमएल एजिलिटी पैक के साथ पार्स करने का प्रयास कर रहा हूं।HtmlAgilityPack

<div class="content-div"> 
    <dl> 
     <dt> 
      <b><a href="1.html" title="1">1</a></b> 
     </dt> 
     <dd> First Entry</dd> 
     <dt> 
      <b><a href="2.html" title="2">2</a></b> 
     </dt> 
     <dd> Second Entry</dd> 
     <dt> 
      <b><a href="3.html" title="3">3</a></b> 
     </dt> 
     <dd> Third Entry</dd> 
    </dl> 
</div> 

मान मैं चाहता हूँ कर रहे हैं:

  • हाइपरलिंक -> 1.html
  • एंकर पाठ -> 1
  • इनर पाठ आयुध डिपो dd -> सबसे पहले एंट्री

(मैंने यहां पहली प्रविष्टि के उदाहरण लिए हैं लेकिन मुझे सूची में सभी प्रविष्टियों के लिए इन तत्वों के मान चाहिए)

इस कोड मैं वर्तमान में उपयोग कर रहा हूँ,

var webGet = new HtmlWeb(); 
      var document = webGet.Load(url2); 
var parsedValues= 
    from info in document.DocumentNode.SelectNodes("//div[@class='content-div']") 
    from content in info.SelectNodes("dl//dd") 
    from link in info.SelectNodes("dl//dt/b/a") 
     .Where(x => x.Attributes.Contains("href")) 
    select new 
    { 
     Text = content.InnerText, 
     Url = link.Attributes["href"].Value, 
     AnchorText = link.InnerText, 
    }; 

GridView1.DataSource = parsedValues; 
GridView1.DataBind(); 
समस्या

है कि मैं लिंक और लंगर पाठ के लिए मूल्यों को सही ढंग से मिल लेकिन इसके बारे में भीतरी पाठ के लिए सिर्फ पहली प्रविष्टि के मान लेता है और तत्वों की कुल संख्या के लिए सभी अन्य प्रविष्टियों के लिए समान मूल्य भरता है और फिर यह दूसरे के साथ शुरू होता है। मैं अपने स्पष्टीकरण में इतना स्पष्ट इसलिए यहाँ नहीं हो सकता है एक नमूना उत्पादन मैं इस कोड के साथ हो रही है है:

First Entry  1.html 1 
First Entry  2.html 2 
First Entry  3.html 3 
Second Entry 1.html 1 
Second Entry 2.html 2 
Second Entry 3.html 3 
Third Entry  1.html 1 
Third Entry  2.html 2 
Third Entry  3.html 3 

जबकि मैं

First Entry  1.html  1 
Second Entry  2.html  2 
Third Entry  3.html  3 

पाने के लिए कोशिश कर रहा हूँ मैं बहुत HAP लिए नया हूँ और बहुत है xpath पर थोड़ा सा ज्ञान, इसलिए मुझे यकीन है कि मैं यहां कुछ गलत कर रहा हूं, लेकिन मैं इसे घंटों खर्च करने के बाद भी काम नहीं कर सका। कोई भी सहायताकाफी प्रशंसनीय होगी।

उत्तर

4

समाधान 1

मैं एक समारोह है कि दिए गए एक dt नोड यह बाद अगले dd नोड वापस आ जाएगी परिभाषित किया है:

private static HtmlNode GetNextDDSibling(HtmlNode dtElement) 
{ 
    var currentNode = dtElement; 

    while (currentNode != null) 
    { 
     currentNode = currentNode.NextSibling; 

     if(currentNode.NodeType == HtmlNodeType.Element && currentNode.Name =="dd") 
      return currentNode; 
    } 

    return null; 
} 

और अब LINQ कोड को तब्दील किया जा सकता:

var parsedValues = 
    from info in document.DocumentNode.SelectNodes("//div[@class='content-div']") 
    from dtElement in info.SelectNodes("dl/dt") 
    let link = dtElement.SelectSingleNode("b/a[@href]") 
    let ddElement = GetNextDDSibling(dtElement) 
    where link != null && ddElement != null 
    select new 
    { 
     Text = ddElement.InnerHtml, 
     Url = link.GetAttributeValue("href", ""), 
     AnchorText = link.InnerText 
    }; 

समाधान 2

अतिरिक्त कार्य के बिना:

var infoNode = 
     document.DocumentNode.SelectSingleNode("//div[@class='content-div']"); 

var dts = infoNode.SelectNodes("dl/dt"); 
var dds = infoNode.SelectNodes("dl/dd"); 

var parsedValues = dts.Zip(dds, 
    (dt, dd) => new 
    { 
     Text = dd.InnerHtml, 
     Url = dt.SelectSingleNode("b/a[@href]").GetAttributeValue("href", ""), 
     AnchorText = dt.SelectSingleNode("b/a[@href]").InnerText 
    }); 
+0

का उपयोग करके कुछ तत्वों का विश्लेषण कैसे कर सकते हैं, यह बहुत काम करता है। हालांकि मैं बिल्कुल समझ नहीं पा रहा हूं कि यहां क्या हो रहा है। क्या यह किसी प्रकार के xpath/regex का उपयोग करके किसी फ़ंक्शन के बिना किया जा सकता है? यह समाधान मेरे लिए बिल्कुल ठीक है, मैं सिर्फ उत्सुक हूं कि यह कैसे काम करता है। यह अच्छा होगा अगर आप एक संक्षिप्त स्पष्टीकरण दे सकते हैं, धन्यवाद। – redGREENblue

+1

समस्या यह है कि हमें "इस 'डीटी' टैग की तरह कुछ चाहिए, मुझे 'डीडी' टैग दें जो इसके तुरंत बाद आता है"। मैंने ddElement को ntElement.NextSibling के रूप में चुनकर इसे आसान बनाने की कोशिश की, लेकिन HtmlAgilityPack अगले नोड को '

' और '
'टैग के बीच व्हाइटस्पेस मानता है। इससे मुझे ऊपर दिखाई देने वाले थोड़ा उलझन समाधान का सामना करना पड़ा। – GolfWolf

+1

मैंने अभी एक और संभावित समाधान निकाला है जिसमें फ़ंक्शन घोषित करने में शामिल नहीं है - कृपया अद्यतन उत्तर देखें। – GolfWolf

2

बस एक उदाहरण Html Agility Pack

public string ParseHtml() 
{ 
    string output = null; 
    HtmlDocument htmldocument = new HtmlDocument(); 
    htmldocument.LoadHtml(YourHTML); 

    HtmlNode node = htmldocument.DocumentNode;  

    HtmlNodeCollection dds = node.SelectNodes("//dd"); //Select all dd tags 
    HtmlNodeCollection anchors = node.SelectNodes("//b/a[@href]"); //Select all 'a' tags that contais href attribute 

    for (int i = 0; i < dds.Count; i++) 
    { 
     string atributteValue = null. 
     Text = dds[i].InnerText; 
     Url = anchors[i].GetAttributeValue("href", atributteValue); 
     AnchorText = anchors[i].InnerText; 

     //Your code... 
    } 
    return output; 
} 
संबंधित मुद्दे