如何解析HTML以修改所有单词

时间:2011-02-11 16:22:29

标签: c# html

这似乎是一个反复出现的问题,但现在就是这样。

我有格式良好的HTML(它来自受控源,所以这可以被认为是给定的)。我需要遍历HTML正文的内容,查找文档中的所有单词,对这些单词执行一些编辑,然后保存结果。

例如,我有文件sample.html,我想通过我的应用程序和产品output.html运行它,这与原始文件完全一样,加上我的编辑。

我使用HTMLAgilityPack找到了以下内容,但是我发现的所有示例都会查看指定标记的属性 - 是否有一个简单的修改,可以查看内容并执行我的编辑?

HtmlDocument HD = new HtmlDocument();
HD.Load (@"e:\test.htm");
var NoAltElements = HD.DocumentNode.SelectNodes("//img[not(@alt)]");
if (NoAltElements != null)
{
    foreach (HtmlNode HN in NoAltElements)
    {
       HN.Attributes.Append("alt", "no alt image");
    }
}

HD.Save(@"e:\test.htm");

以上查找没有ALT标签的图片标签。我想在文件的<body>中查找所有标签,并对内容执行某些操作(可能涉及在此过程中创建新标签)。

我可能做的一个非常简单的示例是采取以下输入:

<html>
    <head><title>Some Title</title></head>
    <body>
        <h1>This is my page</h1>
        <p>This is a paragraph of text.</p>
    </body>
</html>

并生成输出,该输出取每个单词并在使其大写并使其斜体之间交替:

<html>
    <head><title>Some Title</title></head>
    <body>
        <h1>THIS <em>is</em> MY <em>page</em></h1>
        <p>THIS <em>is</em> A <em>paragraph</em> OF <em>text</em>.</p>
    </body>
</html>

想法,建议?

2 个答案:

答案 0 :(得分:5)

就个人而言,给定此设置,我将使用HtmlNode的InnerText属性来查找单词(可能使用Regex,因此我可以排除标点符号而不是简单地依赖空格)然后使用InnerHtml属性进行更改使用对Regex.Replace的迭代调用(因为Regex.Replace有一个方法,允许您指定开始位置和要替换的次数)。

处理代码:

IEnumerable<HtmlNode> nodes = doc.DocumentNode.DescendantNodes().Where(n => n.InnerText == "something");
foreach (HtmlNode node in nodes)
{
    string[] words = getWords(node.InnerText);

    node.InnerHtml = processHtml(node.InnerHtml, words);
}

识别单词(可能有一些更流畅的方式来执行此操作,但这是最初的刺戳):

private string[] getWords(string text)
{
    Regex reg = new Regex("/w+");
    MatchCollection matches = reg.Matches(text);
    List<string> words = new List<string>();
    foreach (Match match in matches)
    {
        words.Add(match.Value);
    }
    return words.ToArray();
}

处理html:

private string processHtml(string html, string[] words)
{
    int startPosition = 0;
    foreach (string word in words)
    {
        startPosition = html.IndexOf(word, startPosition);
        Regex reg = new Regex(word);
        html = reg.Replace(html, alterWord(word), 1, startPosition);
    }

    return html;
}

我会将alterWord()的详细信息留给您。 :)

答案 1 :(得分:3)

试试.SelectNodes("//body//*")。这将使你在任何深度的任何body元素中获得所有元素。