Trouver tous les éléments avec une chaîne de texte?

c# html html-agility-pack xpath

Question

J'essaie de supprimer tous les éléments HTML (balises) contenant une chaîne de texte spécifique. J'ai 2376 documents HTML, tous avec des normes de doctype différentes. Certains n'ont même pas de doctype (peut ne pas être pertinent pour cette question).

Donc, je cherche une chaîne de texte qui dit "Comment citer ce document", et j’ai trouvé qu’il était enfermé dans une <p>-tag , <h4>-tag ou <legend>-tag

La <p>-tag souvent à ceci,

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

La <h4>-tag souvent à ceci,

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

La <legend>-tag ressemble à ceci,

<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 tâche à accomplir consiste à rechercher ces balises, à les supprimer du fichier, puis à enregistrer à nouveau le fichier. J'ai plus de balises à supprimer, mais j'ai besoin d'aide pour comprendre HAP et XPath et savoir comment localiser des balises spécifiques en fonction de leurs valeurs ou d'autres données uniques.

Jusqu'à présent, j'ai mis ce code en C #, c'est une application console. Ceci est ma principale (désolé pour la mauvaise indentation),

//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();

Et c'est la méthode privée qui cherche dans les répertoires les fichiers,

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

La seule chose qui semble être "Comment citer ce document" alors j'essaie de trouver toutes les balises spécifiques qui contiennent ces mots exacts, puis de les supprimer. Mon bloc-notes indique qu'il devrait y avoir 1094 fichiers avec cette phrase. J'essaie donc de tous les obtenir. :)

Toute aide grandement appréciée! :)

Réponse acceptée

Html Agility Pack supporte les sélecteurs LINQ, ce qui est très pratique dans ce cas. Étant donné le code HTML basé sur votre exemple ci-dessus:

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

Vous pouvez créer une collection de balises à rechercher, sélectionner les nœuds correspondants, puis les supprimer comme suit:

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

Avec le résultat suivant:

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



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi