Как пройти FSharp.Data HtmlDocument для извлечения содержимого в виде строки? - PullRequest
1 голос
/ 20 марта 2020

Я хотел бы написать функцию, которая выводит меня из этой html:

<div>
  <h1>Some header.</h1>
  <ul>
    <li>
      <p>Hello world!</p>
    </li>
    <li>
      <p>What is going on? <a href="http://example.com">This is a link</a>.</p>
    </li>
  </ul>
</div>

в эту строку:

Некоторый заголовок. Привет мир! Что здесь происходит? Это ссылка.

Другими словами: я хотел бы пройти этот тест:

let testInput: string = """
<div>
  <h1>Some header.</h1>
  <ul>
    <li>
      <p>Hello world!</p>
    </li>
    <li>
      <p>What is going on? <a href="http://example.com">This is a link</a>.</p>
    </li>
  </ul>
</div>
"""

let getContentsFromHtmlDocument (doc: HtmlDocument) =
  let getInner (node: HtmlNode): string =
    // How can I traverse this tree?
    ""
  let result =
    doc.Descendants ["h1"; "p"; "a"]
    |> Seq.map getInner
    |> List.ofSeq
    |> List.fold (+) ""
  result

[<Test>]
let Test1 () =
    let htmlDoc: HtmlDocument = HtmlDocument.Parse(testInput)
    let res = getContentsFromHtmlDocument htmlDoc
    Assert.AreEqual("Some header. Hello world! What is going on? This is a link.", res)

Но у меня возникли проблемы с выяснением, как пройти по дереву. Любая помощь будет оценена! Спасибо.

1 Ответ

1 голос
/ 20 марта 2020

В HtmlNodeExtensions есть метод расширения, который предоставляет методы, которые вы обычно используете для обхода дерева. Для вашего конкретного случая использования есть HtmlNodeExtensions.DirectInnerText(n).

Хотя для прохождения теста вам понадобится разделенный пробелами внутренний текст, который гораздо эффективнее выполняется с помощью String.Join.

let getContentsFromHtmlDocument (doc: HtmlDocument) =
    let getInner (node: HtmlNode): string =
        node.DirectInnerText()

    let result =
        doc.Descendants ["h1"; "p"; "a"]
        |> Seq.map getInner
        |> fun all -> String.Join(" ", all)

    result

Все еще существует вопрос:

<p>What is going on? <a href="http://example.com">This is a link</a>.</p>

Это будет объединяться с:

What is going on? . This is a link в отличие от What is going on? This is a link., который не может быть обработан с вашей текущей структурой.

...