Obtener contenido entre dos etiquetas HTML usando Html Agility Pack

.net c# html-agility-pack

Pregunta

Tenemos un documento de ayuda absolutamente masivo creado en Word y esto se usó para generar un documento HTM aún más masivo e inaudito. Utilizando C # y esta biblioteca, solo quiero capturar y mostrar una sección de este archivo en cualquier punto de mi aplicación. Las secciones se dividen así:

<!--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>

Hablando lógicamente, hay un H1 con un nombre de sección en a etiqueta. Quiero seleccionar todo desde el div que contiene exterior hasta que encuentre otro h1 y excluir ese div.

  • Cada nombre de sección se encuentra en una etiqueta <a> debajo de un h1 que tiene varios hijos (aproximadamente 6 cada uno)
  • La sección lógica está marcada con comentarios.
  • Estos comentarios no existen en el documento actual.

Mi intento:

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, no he podido encontrar documentación sobre esto, no sé cómo puedo pasar de mi nodo de inicio al siguiente elemento h1. Cualquier sugerencia sera apreciada.

Respuesta aceptada

Creo que esto lo hará, aunque asume que las etiquetas H1 solo aparecen en los encabezados de las secciones. Si ese no es el caso, puede agregar un Where en los descendientes para buscar otros filtros en cualquier nodo H1 que encuentre. Tenga en cuenta que esto incluirá a todos los hermanos del div que encuentre hasta que llegue al siguiente con un nombre de sección.

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;
}

Respuesta popular

Entonces, ¿qué es lo que realmente quieres como resultado es la división alrededor de la etiqueta h1? Si es así, entonces esto debería funcionar.

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

También funciona con SelectNodes dependiendo de su Html. Me gusta esto:

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

Ah, y mientras probaba esto, noté que lo que no funcionaba para mí era el punto en el método de contenido, una vez que lo cambio por el atributo de nombre, todo funciona bien.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué