получить все узлы и его содержимое с помощью htmldocument / HtmlAgilityPack

c# html html-agility-pack uwp

Вопрос

Мне нужно получить все узлы из html, затем из этих узлов мне нужно получить текст и под-узлы, а также то же самое, но из этих под-узлов. Например, у меня есть этот HTML:

<p>This <b>is a <a href="">Link</a></b> with <b>bold</b></p>

Поэтому мне нужен способ получить p- узел, затем неформатированный текст (это), только полужирный текст ( это a ), выделенная жирным шрифтом ссылка ( Link ), а остальная часть отформатированного и не форматированного текста.

Я знаю, что с помощью htmldocument я могу выбрать все узлы и под-узлы, но как я могу получить текст перед субузлом, затем подузел и его текст / под-узлы, чтобы я мог сделать рендерную версию html («Это ссылка с жирным шрифтом »)?

Обратите внимание, что приведенный выше пример является простым. HTML будет иметь более сложные вещи, такие как список, фреймы, нумерованный список, текст с тройным форматированием и т. Д. Также обратите внимание, что сделанная вещь не является проблемой. Я уже это сделал, но по-другому. Мне нужна часть, чтобы получить только узлы и контент. Кроме того, я не могу игнорировать любой узел, поэтому я не могу фильтровать ничем. И главный узел может начинаться как p, div, frame, ul и т. Д.

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

Посмотрев в htmldoc и его свойствах, и благодаря наблюдению @HungCao, я получил простой простой способ интерпретировать HTML-код.

Мой код немного сложнее добавить его в качестве примера, поэтому я опубликую его версию.

Прежде всего, должен быть загружен htmlDoc. Это может быть любая функция:

HtmlDocument htmlDoc = new HtmlDocument();
string html = @"<p>This <b>is a <a href="""">Link</a></b> with <b>bold</b></p>";
htmlDoc.LoadHtml(html);

Затем нам нужно интерпретировать каждый «главный» узел (p в этом случае) и, в зависимости от его типа, нам нужно загрузить LoopFunction (InterNode)

HtmlNodeCollection nodes = htmlDoc.DocumentNode.ChildNodes;

foreach (HtmlNode node in nodes)
{
    if(node.Name.ToLower() == "p") //Low the typeName just in case
    {
        Paragraph newPPara = new Paragraph();
        foreach(HtmlNode childNode in node.ChildNodes)
        {
            InterNode(childNode, ref newPPara);
        }
        richTextBlock.Blocks.Add(newPPara);
    }
}

Обратите внимание, что есть свойство, называемое «NodeType», но оно не вернет правильный тип. Итак, вместо этого используйте свойство Name (Также обратите внимание, что свойство Name в htmlNode не совпадает с атрибутом Name в HTML).

Наконец, у нас есть функция InterNode, которая добавит строки в указанный (ref) абзац

public bool InterNode(HtmlNode htmlNode, ref Paragraph originalPar)
{
    string htmlNodeName = htmlNode.Name.ToLower();

    List<string> nodeAttList = new List<string>();
    HtmlNode parentNode = htmlNode.ParentNode;
    while (parentNode != null) {
        nodeAttList.Add(parentNode.Name);
        parentNode = parentNode.ParentNode;
    } //we need to get it multiple types, because it could be b(old) and i(talic) at the same time.

    Inline newRun = new Run();
    foreach (string noteAttStr in nodeAttList) //with this we can set all the attributes to the inline
    {
        switch (noteAttStr)
        {
            case ("b"):
            case ("strong"):
                {
                    newRun.FontWeight = FontWeights.Bold;
                    break;
                }
            case ("i"):
            case ("em"):
                {
                    newRun.FontStyle = FontStyle.Italic;
                    break;
                }
        }
    }

    if(htmlNodeName == "#text") //the #text means that its a text node. Like <i><#text/></i>. Thanks @HungCao
    {
        ((Run)newRun).Text = htmlNode.InnerText;
    } else //if it is not a #text, don't load its innertext, as it's another node and it will always have a #text node as a child (if it has any text)
    {
        foreach (HtmlNode childNode in htmlNode.ChildNodes)
        {
            InterNode(childNode, ref originalPar);
        }
    }

    return true;
}

Примечание. Я знаю, что я сказал, что мое приложение должно отображать HTML по-другому, что делает веб-просмотр, и я знаю, что этот примерный код генерирует то же, что и Webview, но, как я уже говорил, это просто облегчение версию моего последнего кода. Фактически, мой оригинальный / полный код работает так, как мне нужно, и это просто база.



Related

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