HtmlAgilityPack cómo extraer HTML entre alguna etiqueta

c# html-agility-pack

Pregunta

Necesito extraer todo el párrafo de un html y también todo el texto entre esas etiquetas.

este código no funciona cuando el texto analizado en HtmlDocument se cambia del original. En la muestra

some <br />text

se cambia en

some <br>text

es

string s = "<p>firt paragraph</p>some <br />text<p>another paragraph</p><span>some text between span</span><p>hellow word</p>";
        HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
        doc.LoadHtml(s);
var nodes = doc.DocumentNode.SelectNodes("//p");
int lastPos = -1;
foreach (HtmlAgilityPack.HtmlNode n in nodes)
{
  if (lastPos > -1)
  {
      string textNotInP = Doc.DocumentNode.OuterHtml.Substring(lastPos, n.StreamPosition - lastPos);
                System.Diagnostics.Debug.WriteLine(textNotInP);
 }
 System.Diagnostics.Debug.WriteLine(n.OuterHtml);
 lastPos = n.StreamPosition + n.OuterHtml.Length;
}

El resultado correcto sería:

<p>firt paragraph</p>
some <br>text
<p>second paragraph</p>
<span>some text between span</span>
<p>third paragraph</p>

pero el código anterior devuelve esto:

<p>firt paragraph</p>
some <br>text<p
<p>second paragraph</p>
pan>some text between span</span><p
<p>third paragraph</p>

la razón es steamPosition devuelve la posición del nodo relacionada con el texto original, no esa parserd en htmlDocument.

¿Hay alguna forma de devolver la posición de un nodo relacionado con el html analizado?

Respuesta aceptada

Puede usar la propiedad OuterHtml de cada elemento <p> para obtener el HTML deseado:

string s = "<p>firt paragraph</p>some <br />text<p>another paragraph</p><span>some text between span</span><p>hellow word</p>";
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(s);
var nodes = doc.DocumentNode.SelectNodes("//p");
foreach (var item in nodes)
{
    Console.WriteLine(item.OuterHtml);
}

salida:

<p>firt paragraph</p>
<p>another paragraph</p>
<p>hellow word</p>

O si quiere obtener todo entre el primer <p> y el último <p> elementos, inclusive, puede usar la siguiente XPath:

var query = "//node()[preceding-sibling::p or self::p][following-sibling::p or self::p]";

El XPath captura todos los nodos (elemento o nodo de texto) que: tiene un hermano p precedente y un p hermano de seguimiento, o el nodo mismo es un elemento p .

var nodes = doc.DocumentNode.SelectNodes(query);
foreach (var item in nodes)
{
    Console.WriteLine(item.OuterHtml);
}

salida:

<p>firt paragraph</p>
some
<br />
text
<p>another paragraph</p>
<span>some text between span</span>
<p>hellow word</p>


Related

Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow