HtmlAgilityPack을 사용하여 노드의 하위 파싱 문제

c# html-agility-pack html-parsing xpath

문제

html로 양식의 입력 태그 하위를 구문 분석하는 데 문제가 있습니다. // input [@type]을 사용하여 루트에서 파싱 할 수 있지만 특정 노드의 하위 노드는 파싱 할 수 없습니다.

문제를 설명하는 코드는 다음과 같습니다.

private const string HTML_CONTENT =
        "<html>" +
        "<head>" +
        "<title>Test Page</title>" +
        "<link href='site.css' rel='stylesheet' type='text/css' />" +
        "</head>" +
        "<body>" +
        "<form id='form1' method='post' action='http://www.someplace.com/input'>" +
        "<input type='hidden' name='id' value='test' />" +
        "<input type='text' name='something' value='something' />" +
        "</form>" +
        "<a href='http://www.someplace.com'>Someplace</a>" +
        "<a href='http://www.someplace.com/other'><img src='http://www.someplace.com/image.jpg' alt='Someplace Image'/></a>" +
        "<form id='form2' method='post' action='/something/to/do'>" +
        "<input type='text' name='secondForm' value='this should be in the second form' />" +
        "</form>" +
        "</body>" +
        "</html>";

public void Parser_Test()
    {
        var htmlDoc = new HtmlDocument
        {
            OptionFixNestedTags = true,
            OptionUseIdAttribute = true,
            OptionAutoCloseOnEnd = true,
            OptionAddDebuggingAttributes = true
        };

        byte[] byteArray = Encoding.UTF8.GetBytes(HTML_CONTENT);
        var stream = new MemoryStream(byteArray);
        htmlDoc.Load(stream, Encoding.UTF8, true);
        var nodeCollection = htmlDoc.DocumentNode.SelectNodes("//form");
        if (nodeCollection != null && nodeCollection.Count > 0)
        {
            foreach (var form in nodeCollection)
            {
                var id = form.GetAttributeValue("id", string.Empty);
                if (!form.HasChildNodes)
                    Debug.WriteLine(string.Format("Form {0} has no children", id ) );

                var childCollection = form.SelectNodes("input[@type]");
                if (childCollection != null && childCollection.Count > 0)
                {
                    Debug.WriteLine("Got some child nodes");
                }
                else
                {
                    Debug.WriteLine("Unable to find input nodes as children of Form");
                }
            }
            var inputNodes = htmlDoc.DocumentNode.SelectNodes("//input");
            if (inputNodes != null && inputNodes.Count > 0)
            {
                Debug.WriteLine(string.Format("Found {0} input nodes when parsed from root", inputNodes.Count ) );
            }
        }
        else
        {
            Debug.WriteLine("Found no forms");
        }
    }

출력은 다음과 같습니다.

Form form1 has no children
Unable to find input nodes as children of Form
Form form2 has no children
Unable to find input nodes as children of Form
Found 3 input nodes when parsed from root

예상 할 수있는 것은 Form1과 Form2는 둘 다 자식을 가지며 입력 [@type]은 form1에 2 노드를 찾고 form2에 1을 찾을 수 있다는 것입니다.

내가 사용하고 있지 않은 특정 구성 설정이나 방법이 있습니까? 어떤 아이디어?

감사,

스티브

수락 된 답변

이제 HtmlAgilityPack을 포기했습니다. 모든 것을 작동 시키려면 라이브러리에서해야 할 일이 아직 많이 남아있는 것처럼 보입니다. 이 문제를 해결하기 위해 여기에서 SGMLReader 라이브러리를 사용하도록 코드를 옮겼습니다. http://developer.mindtouch.com/SgmlReader

이 라이브러리를 사용하면 모든 유닛 테스트가 제대로 통과하고 샘플 코드가 예상대로 작동합니다.


인기 답변

HtmlAgilityPack 사이트의이 토론 스레드를 확인하십시오. - http://htmlagilitypack.codeplex.com/workitem/21782

이것은 그들이 말하는 것입니다 :

이것은 버그가 아니며 기능이며 구성 가능합니다. FORM은 많은 HTML 페이지가 중복 된 양식을 사용했기 때문에 이와 같이 취급됩니다. 원래 HTML의 (강력한) 기능 이었기 때문입니다. 이제 XML과 XHTML이 존재하기 때문에 모든 사람들이 겹치는 부분은 오류라고 가정하지만 HTML 3.2에서는 그렇지 않습니다. HtmlNode.cs 파일을 확인하고 ElementsFlags 컬렉션을 수정합니다 (또는 원하는 경우 런타임에 수행).

HtmlNode.cs 파일을 수정하려면 다음 줄을 주석으로 처리하십시오.

ElementsFlags.Add("form", HtmlElementFlag.CanOverlap | HtmlElementFlag.Empty);


아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.