HtmlElement没有正确解析标记

时间:2013-08-26 13:59:54

标签: c# html5 webbrowser-control

我的html源代码中有以下行:

<input class="phone" name="site_url" type="text" placeholder="Enter Your Website URL">

当我使用WebBrowser Control(C#)导航并将我的网站加载到HtmlDocument对象,然后遍历每个HtmlElement时,当我到达上面的input元素时:

我无法获得占位符属性。 GetAttribute(“placeholder”)返回“”。 我检查了OuterHtml / InnerHtml字段并注意到占位符属性是用“”复制而其他属性不是,而且,我可以检索其他属性(名称,类)。

这是InnerHtml / OuterHtml的输出:

<INPUT class=phone placeholder="Enter Your Website URL" name=site_url>

任何人都可以解释为什么会这样,在这种情况下如何更改占位符?

2 个答案:

答案 0 :(得分:2)

默认情况下,WebBrowser控件在IE7兼容模式下运行。在该模式下,不支持placeholder属性。因此,首先需要将其切换到IE10模式here's how。然后,您需要调用非托管getAttributeNode并获取其value,具体如下:

bool FindElementWithPlaceholder(HtmlElement root, string placeholder, ref HtmlElement found, ref string value)
{
    foreach (var child in root.Children)
    {
        var childElement = (HtmlElement)child;
        dynamic domElement = childElement.DomElement;
        dynamic attrNode = domElement.getAttributeNode(placeholder);
        if (attrNode != null)
        {
            string v = attrNode.value;
            if (!String.IsNullOrWhiteSpace(v))
            {
                value = v;
                found = childElement;
                return true;
            }
        }
        if (FindElementWithPlaceholder(childElement, placeholder, ref found, ref value))
            return true;
    }
    return false;
}

// ...

HtmlElement element = null;
string value = null;
if (FindElementWithPlaceholder(this.WB.Document.Body, "placeholder", ref element, ref value))
    MessageBox.Show(value);

此代码已经过IE10测试。

[已编辑] 您仍然可以使用上述代码检索placeholder的值,即使WebBrowser Feature Control未实现也是如此。但是,placeholder在这种情况下不会在视觉上起作用,因为文档不会处于HTML5模式。

[编辑] 也许,我终于明白了你的想法。尝试此代码,看看是否这样做。您仍需要功能控件和DOCTYPE才能启用HTML5。

HTML: <!doctype html><html><input class=phone placeholder=\"Enter Your Website URL\" name=site_url></html>

HtmlElement element = null;
string oldValue = null;
string newValue = "New Value";
FindElementWithPlaceholder(this.webBrowser1.Document.Body, "placeholder", ref element, ref value, newValue);

bool FindElementWithPlaceholder(HtmlElement root, string placeholder, ref HtmlElement found, ref string oldValue, string newValue)
{
    foreach (var child in root.Children)
    {
        var childElement = (HtmlElement)child;
        dynamic domElement = childElement.DomElement;
        dynamic attrNode = domElement.getAttributeNode(placeholder);
        if (attrNode != null)
        {
            string v = attrNode.value;
            if (!String.IsNullOrWhiteSpace(v))
            {
                domElement.removeAttributeNode(attrNode);
                domElement.setAttribute(placeholder, newValue);
                // a hack to make IE10 to render the new placeholder  
                var id = domElement.getAttribute("id");
                var uniqueId = Guid.NewGuid().ToString();
                domElement.setAttribute("id", uniqueId);
                var html = domElement.outerHTML;
                domElement.outerHTML = html;
                var newElement = root.Document.GetElementById(uniqueId);
                domElement = newElement.DomElement;
                if (String.IsNullOrEmpty(id))
                    domElement.removeAttribute("id");
                else
                    domElement.setAttribute("id", id);
                found = newElement;
                oldValue = v;
                return true;
            }
        }
        if (FindElementWithPlaceholder(childElement, placeholder, ref found, ref oldValue, newValue))
            return true;
    }
    return false;
}

答案 1 :(得分:1)

  

HtmlElement只公开所有元素共有的属性,而忽略那些仅适用于某些类型元素的属性;

HtmlElement.GetAttribute与IHTMLElement :: getAttribute(strAttributeName,0)相同

关于getAttribute与Internet Explorer 8相关的工作方式有一些变化,请查看备注部分。要解决此问题,您可以手动解析InnerHtml以提取该自定义占位符属性。