Проблема синтаксического анализа дочерних узлов узла с помощью 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] сможет найти 2 узла для form1 и 1 для form2

Есть ли определенный параметр конфигурации или метод, который я не использую, что я должен быть? Есть идеи?

Благодаря,

Стив

Принятый ответ

Ну, теперь я отказался от 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);


Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow