est-il possible de résoudre le problème dans HtmlAgilityPack quand il y a une balise HTML non fermée?
-
20-09-2019 - |
Question
Eh bien, j'ai le problème suivant.
le code html que j'ai est malformé et j'avoir des problèmes avec la sélection des noeuds en utilisant pack agilité html lorsque cela est le cas.
le code est ci-dessous:
string strHtml = @"
<html>
<div>
<p><strong>Elem_A</strong>String_A1_2 String_A1_2</p>
<p><strong>Elem_B</strong>String_B1_2 String_B1_2</p>
</div>
<div>
<p><strong>Elem_A</strong>String_A2_2 <String_A2_2> asdas</p>
<p><strong>Elem_B</strong>String_B2_2 String_B2_2</p>
</div>
</html>";
HtmlAgilityPack.HtmlDocument objHtmlDocument = new HtmlAgilityPack.HtmlDocument();
objHtmlDocument.LoadHtml(strHtml);
HtmlAgilityPack.HtmlNodeCollection colnodePs = objHtmlDocument.DocumentNode.SelectNodes("//p");
List<string> lststrText = new List<string>();
foreach (HtmlAgilityPack.HtmlNode nodeP in colnodePs)
{
lststrText.Add(nodeP.InnerHtml);
}
le problème est que String_A2_2 est placé entre crochets.
si pack htmlagility retourne 5 chaînes au lieu de 4 dans le lststrText.
donc est-il possible de laisser l'élément de retour pack htmlagility 3 comme
"<strong>Elem_A</strong>String_A2_2 <String_A2_2> asdas"
ou peut-être que je peux faire un peu de pré-traitement pour fermer l'élément
le contenu actuel de lststrText est
lststrText[0] = "<strong>Elem_A</strong>String_A1_2 String_A1_2"
lststrText[1] = "<strong>Elem_B</strong>String_B1_2 String_B1_2"
lststrText[2] = ""
lststrText[3] = ""
lststrText[4] = "<strong>Elem_B</strong>String_B2_2 String_B2_2"
La solution
La plupart des parseurs html essayer de construire un DOM de travail, ce qui signifie balises ballants ne sont pas acceptés. Ils seront convertis ou fermés en quelque sorte.
Si seulement le choix des nœuds est d'importance pour vous, et la vitesse et d'énormes quantités de données ne sont pas un problème, vous pouvez saisir vos
avec une expression régulière à la place:
Regex reMatchP = new Regex(@"<(p)>.*?</\1>");
foreach (Match m in reMatchP.Matches(strHtml))
{
Console.WriteLine(m.Value);
}
Cette expression régulière suppose que les
balises sont bien formées et fermées.
Si vous êtes à exécuter ce Regex beaucoup dans votre programme, vous annonciez comme:
static Regex reMatchP = new Regex(@"<(p)>.*?</\1>", RegexOptions.Compiled);
[Edit: Agilité changement pack]
Si vous voulez utiliser emballer HtmlAgility vous pouvez modifier la fonction PushNodeEnd dans HtmlDocument.cs:
if (HtmlNode.IsCDataElement(CurrentNodeName()))
{
_state = ParseState.PcData;
return true;
}
// new code start
if ( !AllowedTags.Contains(_currentnode.Name) )
{
close = true;
}
// new code end
où AllowedTags serait une liste de toutes les balises connues:. B, p, br, durée, div, etc
la sortie n'est pas 100% ce que vous voulez, mais peut-être assez proche?
<strong>Elem_A</strong>String_A1_2 String_A1_2
<strong>Elem_B</strong>String_B1_2 String_B1_2
<strong>Elem_A</strong>String_A2_2 <ignorestring_a2_2></ignorestring_a2_2> asdas
<strong>Elem_B</strong>String_B2_2 String_B2_2