2

在 C# 中,如何获取 System.Windows.Form.HtmlElement 的文本,不包括其子项的文本?

如果我有

<div>aaa<div>bbb<div>ccc</div><div>ddd</div></div></div>

那么整个事物的 InnerText 属性是“aaabbbcccddd”,我只想要“aaa”。

我认为这应该是微不足道的,但我还没有找到任何东西可以在 C# 中生成 HtmlElement 的“立即”文本。更可笑的想法是从父级中“减去”子级的 InnerText,但对于我确信是微不足道的事情来说,这是一个疯狂的工作量。

(我想要的只是访问 HtmlElement 的文本节点。)

我肯定会感谢任何人可以提供的任何帮助(或指针)。

非常感谢。

例子:

<div>aaa<div>bbb<div>ccc</div><div>ddd</div></div></div>  -> Produce "aaa"
<div><div>ccc</div><div>ddd</div></div>                   -> Produce ""
<div>ccc</div>                                            -> Produce "ccc" 

编辑

有很多方法可以给这只特殊的猫剥皮,但没有一种是优雅的。但是,鉴于我的限制(不是我的 HTML,很可能无效),我认为 Aleksey Bykov 的解决方案最接近我需要的解决方案(实际上,我确实实施了他在上一条评论中建议的相同解决方案。)

我选择了他的解决方案,并对我认为可行但对我来说不是最佳的所有其他解决方案都投了赞成票。我会回来检查以支持任何其他似乎可能有效的解决方案。

非常感谢。

4

3 回答 3

1

也许它比这更简单,如果您愿意使用 XmlDocument 而不是 HtmlDocument - 您可以只使用 XmlElement 的“值”属性。

此代码为您提到的 3 种情况提供了您想要的输出:

class Program
{
    private static string[] htmlTests = {@"<div>aaa<div>bbb<div>ccc</div><div>ddd</div></div></div>",
                                         @"<div><div>ccc</div><div>ddd</div></div>",
                                         @"<div>ccc</div>" };
    static void Main(string[] args)
    {
        var page = new XmlDocument();

        foreach (var test in htmlTests)
        {
            page.LoadXml(test);
            Console.WriteLine(page.DocumentElement.FirstChild.Value);
        }
    }
}

输出:

aaa

ccc
于 2013-11-11T04:57:28.513 回答
0

我不确定 HtmlElement 是什么意思,但是使用 XmlElement 你会这样做:

using System;
using System.Xml;
using System.Linq;
using System.Collections.Generic;
using System.Text;

public static class XmlUtils {

    public static IEnumerable<String> GetImmediateTextValues(XmlNode node) {
        var values = node.ChildNodes.Cast<XmlNode>().Aggregate(
            new List<String>(),
            (xs, x) => { if (x.NodeType == XmlNodeType.Text) { xs.Add(x.Value); } return xs; }
        );
        return values;
    }

    public static String GetImmediateJoinedTextValues(XmlNode node, String delimiter) {
        var values = GetImmediateTextValues(node);
        var text = String.Join(delimiter, values.ToArray());
        return text;
    }
}

编辑:

好吧,如果您的HtmlElement来自 System.Windows.Forms,那么您需要做的是使用其DomElement属性尝试将其转换为mshtml中定义的 COM 接口之一。因此,您需要做的就是能够判断您正在查看的元素是否是文本节点并获取其值。首先,您必须添加对 mshtml COM 库的引用。您可以这样做(我无法立即验证此代码)。

public Bool IsTextNode(HtmlElement element) {
  var result = false;
  var nativeNode = element.DomElement as mshtml.IHTMLDOMNode;
  if (nativeNode != null) {
      var nodeType = nativeNode.nodeType;
      result = nodeType == 3; // -- TextNode: http://msdn.microsoft.com/en-us/library/aa704085(v=vs.85).aspx
  }
  return result

}

于 2013-11-11T04:29:45.890 回答
-1

好吧,你可以做这样的事情(假设你的输入在一个名为 `input' 的字符串中):

string pattern = @">.*?<";
Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase); 

MatchCollection matches = rgx.Matches(input);
var first_match = matches[0].ToString();
string result = first_match.Substring(1, first_match.Length - 2);

我可能不会这样做(或者只是中继匹配第一个<div>和的字符串</div>)......在这里,以获得额外的荣誉:

int start = pattern.IndexOf(">") + 1;
int end = pattern.IndexOf("<", start);
string result = input.Substring(start, end - start);
于 2013-11-11T04:45:46.130 回答