2

好吧,我有以下问题。
我拥有的 html 格式不正确,在这种情况下,我在使用 html 敏捷包选择节点时遇到问题。
代码如下:

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

问题是 String_A2_2 括在括号中。
所以 htmlagility 包在 lststrText 中返回 5 个字符串而不是 4 个。
那么是否可以让 htmlagility pack 将元素 3 返回为 "<strong>Elem_A</strong>String_A2_2 <String_A2_2> asdas"
或者我可以做一些预处理来关闭元素?
lststrText 的当前内容是

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

2 回答 2

2

您可以使用TidyNet进行您提到的预处理/后处理。您可以编辑您的答案以解释为什么这不适用于您的情况吗?

于 2009-12-23T14:26:51.817 回答
2

大多数 html 解析器都试图构建一个有效的 DOM,这意味着不接受悬空标签。它们将被转换或以某种方式关闭。

如果只选择节点对您很重要,并且速度和大量数据不是问题,您可以使用正则表达式获取所有 <p> 标签:

Regex reMatchP = new Regex(@"<(p)>.*?</\1>");
foreach (Match m in reMatchP.Matches(strHtml))
{
   Console.WriteLine(m.Value);
}

此正则表达式假定 <p> 标记格式正确且闭合。

如果您要在程序中大量运行此 Regex,您应该将其声明为:

static Regex reMatchP = new Regex(@"<(p)>.*?</\1>", RegexOptions.Compiled);

[编辑:敏捷包更改]

如果要使用 HtmlAgility 包,可以修改 HtmlDocument.cs 中的 PushNodeEnd 函数:

if (HtmlNode.IsCDataElement(CurrentNodeName()))
{
   _state = ParseState.PcData;
   return true;
}

// new code start
if ( !AllowedTags.Contains(_currentnode.Name) )
{
    close = true;
}
// new code end

其中 AllowedTags 将是所有已知标签的列表:b、p、br、span、div 等。

输出不是您想要的 100%,但可能足够接近?

<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
于 2009-12-25T23:05:57.400 回答