글쎄 난 다음과 같은 문제가 있습니다.
내가 가지고있는 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에서 4 대신 5 개의 문자열을 반환합니다.
htmlagility 팩 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"
대부분의 HTML 파서는 작동하는 DOM을 만들려고합니다. 즉, 매달려있는 태그는 허용되지 않습니다. 그들은 어떤 방식 으로든 개종하거나 폐쇄 될 것입니다.
노드 만 선택하는 것이 중요하고 속도와 방대한 양의 데이터가 문제가되지 않는다면 정규식으로 모든 <p> 태그를 대신 잡을 수 있습니다.
Regex reMatchP = new Regex(@"<(p)>.*?</\1>");
foreach (Match m in reMatchP.Matches(strHtml))
{
Console.WriteLine(m.Value);
}
이 정규식은 <p> 태그가 올바르게 구성되어 있고 닫혀 있다고 가정합니다.
프로그램에서이 정규식을 많이 실행하려면 다음과 같이 선언해야합니다.
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
TidyNet 을 사용하여 언급 한 사전 / 사후 처리 작업을 수행 할 수 있습니다. 귀하의 답변을 편집하여 귀하의 사례에 해당되지 않는 이유를 설명 할 수 있습니까?