¿Encontrar todos los elementos con cadena de texto?

c# html html-agility-pack xpath

Pregunta

Estoy tratando de eliminar todos los elementos html (etiquetas) que contienen una cadena de texto específica. Tengo 2376 documentos html, todos con diferentes tipos de documentos. Algunos incluso no tienen un tipo de documento (puede ser irrelevante para esta pregunta).

Por lo tanto, estoy buscando una cadena de texto que diga "Cómo citar este documento", y encontré que está encerrado dentro de un <p>-tag , <h4>-tag o un <legend>-tag .

La <p>-tag menudo se ve así,

<p style="text-align : center; color : Red; font-weight : bold;">How to cite this paper:</i></p>

La <h4>-tag menudo se ve así.

<h4>How to cite this paper:</h4>Antunes, P., Costa, C.J. &amp; Pino, J.A. (2006).

La <legend>-tag parece a esto,

<legend style="color: white; background-color: maroon; font-size: medium; padding: .1ex .5ex; border-right: 1px solid navy; border-bottom: 1px solid navy; font-weight: bold;">How to cite this paper</legend>

La tarea en cuestión es encontrar estas etiquetas y eliminarlas del archivo, y luego guardar el archivo nuevamente. Tengo más etiquetas que eliminar, pero necesito ayuda para entender HAP y XPath, y cómo ubicar etiquetas específicas en función de sus valores u otros datos únicos.

Hasta ahora he creado este código en C #, es una aplicación de consola. Este es mi principal (perdón por mala sangría),

//Variables
string Ext = "*.html";
string folder = @"D:\websites\dev.openjournal.tld\public\arkivet\";
IEnumerable<string> files = GetHTMLFiles(folder, Ext);
List<string> cite_files = new List<string>();            
var doc = new HtmlDocument();

//Loop to match all html-elements to query
foreach (var file in files)
{
 try
   {
      doc.Load(file);
      cite_files.Add(doc.DocumentNode.SelectNodes("//h4[contains(., 'How to cite this paper')]").ToString()); 

     cite_files.Add(doc.DocumentNode.SelectNodes("//p[contains(., 'How to cite this paper')]").ToString());
   }                
                    catch (Exception Ex)
                    {
                        Console.WriteLine(Ex.Message);
                    }
                }

                //Counts numbers of hits and prints data to user
                int filecount = files.Count();
                int citations = cite_files.Count();            
                Console.WriteLine("Number of files scanned: " + filecount);
                Console.WriteLine("Number of citations: {0}", citations);

                // Program end
                Console.WriteLine("Press any key to close program....");
                Console.ReadKey();

Y este es el método privado que busca en los directorios los archivos,

//List all HTML-files recursively and return them to a list 
 public static IEnumerable<string> GetHTMLFiles(string directory, string Ext)
    {
        List<string> files = new List<string>();

        try
        {
            files.AddRange(Directory.GetFiles(directory, Ext, SearchOption.AllDirectories));
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }            
        return files;
    }

Lo único que parece ser "Cómo citar este documento", así que estoy tratando de encontrar todas las etiquetas específicas que contienen estas palabras exactas y luego eliminarlas. Mi Bloc de notas muestra que debería haber 1094 archivos con esta frase, así que estoy tratando de obtenerlos todos. :)

Cualquier ayuda muy apreciada! :)

Respuesta aceptada

Html Agility Pack es compatible con los selectores LINQ, lo cual es muy conveniente en este caso. Dado un poco de HTML basado en su ejemplo anterior:

var html =
@"<html><head></head><body>

<!-- selector match: delete these nodes -->
<p style='text-align: center; color: Red; font-weight: bold;'>How to cite this paper:</i></p>
<h4> How to cite this paper:</h4> Antunes, P., Costa, C.J. & amp; Pino, J.A. (2006).
<legend style='color: white; background-color: maroon; font-size: medium; padding: .1ex .5ex; border-right: 1px solid navy; border-bottom: 1px solid navy; font-weight: bold;'>How to cite this paper </legend>
<div><p><i><b>How to cite this paper (NESTED)</b></i></p></div>

<!-- no match: keep these nodes -->
<p>DO NOT DELETE - How to cite</p>
<h4>DO NOT DELETE - cite this paper:</h4>
<legend>DO NOT DELETE</legend>

</body></html>";

Puede crear una colección de etiquetas en las que se debe buscar, seleccionar nodos coincidentes y luego eliminarlos de esta forma:

var tagsToDelete = new string[] { "p", "h4", "legend" };
var nodesToDelete = new List<HtmlNode>();

var document = new HtmlDocument();
document.LoadHtml(html);
foreach (var tag in tagsToDelete)
{
    nodesToDelete.AddRange(
        from searchText in document.DocumentNode.Descendants(tag)
            where searchText.InnerText.Contains("How to cite this paper")
            select searchText
    );
}

foreach (var node in nodesToDelete) node.Remove();

document.Save(OUTPUT);

Con el siguiente resultado:

<html><head></head><body>

<!-- XPath match: delete these nodes -->

 Antunes, P., Costa, C.J. & amp; Pino, J.A. (2006).

<div></div>

<!-- no match, keep these nodes -->
<p>DO NOT DELETE - How to cite</p>
<h4>DO NOT DELETE - cite this paper:</h4>
<legend>DO NOT DELETE</legend>

</body></html>


Related

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é