Ottenere contenuti tra due tag HTML utilizzando Html Agility Pack

.net c# html-agility-pack

Domanda

Abbiamo un documento di aiuto assolutamente massiccio creato in Word e questo è stato utilizzato per generare un documento HTM ancora più massiccio e sgradito. Usando C # e questa libreria, voglio solo catturare e visualizzare una sezione di questo file in qualsiasi punto della mia applicazione. Le sezioni sono suddivise in questo modo:

<!--logical section starts here -->
<div>
<h1><span style='mso-spacerun:yes'></span><a name="_Toc325456104">Section A</a></h1>
</div>
 <div> Lots of unnecessary markup for simple formatting... </div>
 .....
<!--logical section ends here -->

<div>
<h1><span style='mso-spacerun:yes'></span><a name="_Toc325456104">Section B</a></h1>
</div>

A rigor di logica, v'è un H1 con un nome di sezione in a tag. Voglio selezionare tutto dal div esterno che contiene finché non incontro un altro h1 ed escludo quel div.

  • Ogni Nome sezione si trova in un tag <a> sotto un h1 che ha più figli (circa 6 ciascuno)
  • La sezione logica è contrassegnata con commenti
  • Questi commenti non esistono nel documento reale

Il mio tentativo:

var startNode = helpDocument.DocumentNode.SelectSingleNode("//h1/a[contains(., '"+sectionName+"')]");
//go up one level from the a node to the h1 element
startNode=startNode.ParentNode;

//get the start index as the index of the div containing the h1 element
int startNodeIndex = startNode.ParentNode.ChildNodes.IndexOf(startNode);

//here I am not sure how to get the endNode location. 
var endNode =?;

int endNodeIndex = endNode.ParentNode.ChildNodes.IndexOf(endNode);

//select everything from the start index to the end index
var nodes = startNode.ParentNode.ChildNodes.Where((n, index) => index >= startNodeIndex && index <= endNodeIndex).Select(n => n);

Sine Non sono stato in grado di trovare la documentazione su questo, non so come posso ottenere dal mio nodo iniziale al prossimo elemento h1. Tutti i suggerimenti sarebbero apprezzati.

Risposta accettata

Penso che lo farà, anche se presume che i tag H1 compaiano solo nei capi sezione. Se questo non è il caso, puoi aggiungere un Where sui discendenti per cercare altri filtri su tutti i nodi H1 che trova. Si noti che questo includerà tutti i fratelli del div che trova fino a quando non arriva al successivo con un nome di sezione.

private List<HtmlNode> GetSection(HtmlDocument helpDocument, string SectionName)
{
    HtmlNode startNode = helpDocument.DocumentNode.Descendants("div").Where(d => d.InnerText.Equals(SectionName, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
    if (startNode == null)
        return null; // section not found

    List<HtmlNode> section = new List<HtmlNode>();
    HtmlNode sibling = startNode.NextSibling;
    while (sibling != null && sibling.Descendants("h1").Count() <= 0)
    {
        section.Add(sibling);
        sibling = sibling.NextSibling;
    }

    return section;
}

Risposta popolare

Quindi, quello che vuoi veramente è il div in giro per il tag h1? Se sì, allora dovrebbe funzionare.

helpDocument.DocumentNode.SelectSingleNode("//h1/a[contains(@name, '"+sectionName+"')]/ancestor::div");

Funziona anche con SelectNodes seconda del tuo Html. Come questo:

helpDocument.DocumentNode.SelectNodes("//h1/a[starts-with(@name,'_Toc')]/ancestor::div");

Oh, e mentre testavo questo ho notato che la cosa che non funzionava per me era il punto nel metodo contains, una volta che l'ho cambiato con l'attributo name, tutto funziona bene.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché