在加载 MSHTML 文档之前删除无效的 URL

Removing invalid URLs from MSHTML document before it is loaded

我使用 MSHTML (IHTMLDocument) 显示离线 HTML 其中可能包含各种链接。这些是从电子邮件 HTML.

加载的

其中一些有 URL 以 // 或 / 开头,例如:

<img src="//www.example.com/image.jpg">

<img src="/www.example.com/image.jpg">

这需要很多时间来解析和显示文档,因为它显然找不到 URL 因为它不是以 http:// 或 https://

开头

我尝试将 <base> 标记注入 <head> 并添加一个本地已知文件夹(该文件夹为空),这样就解决了这个问题。例如:

<base href="C:\myemptypath\">

但是,如果链接以 \\(UNC 路径)开头,同样的问题和较长的加载时间再次开始。喜欢:

<img src="\www.something.com\image.jpg">

我还尝试将 WebBrowser 控件置于“离线”模式以及我能想到但无法想出任何缺少 RegEx 的所有其他技巧并替换 [=56= 中的所有链接] 这将是非常缓慢的解决方案(或者我自己解析 HTML 这违背了 MSHTML 的目的)。

有没有办法:

尽管我使用的是Delphi和C++(C++ Builder),但我欢迎任何语言的任何示例,因为我只需要这里的原理在哪个方向看。

经过很长一段时间,这是我使用的解决方案:

创建了一个 CLSID_HTMLDocument 的实例来解析 HTML:

DelphiInterface<IHTMLDocument2> diDoc;
OleCheck(CoCreateInstance(CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&diDoc)));

使用Document->write

IHTMLDocument2写入diDoc
// Creates a new one-dimensional array
WideString HTML = "Example HTML here...";
SAFEARRAY *psaStrings = SafeArrayCreateVector(VT_VARIANT,0,1);

if (psaStrings)
    {
    VARIANT *param;
    BSTR bstr = SysAllocString(HTML.c_bstr());
    SafeArrayAccessData(psaStrings, (LPVOID*)&param);
    param->vt      = VT_BSTR;
    param->bstrVal = bstr;
    SafeArrayUnaccessData(psaStrings);
    diDoc->write(psaStrings);
    diDoc->close();

    // SafeArrayDestroy calls SysFreeString for each BSTR
    //SysFreeString(bstr);  // SafeArrayDestroy should be enough
    SafeArrayDestroy(psaStrings);

    return S_OK;
    }

解析 diDoc

中不需要的链接
DelphiInterface<IHTMLElementCollection> diCol;
if (SUCCEEDED(diDoc->get_all(&diCol)) && diCol)
    {
    // Parse IHTMLElementCollection here...
    }

将解析的 HTML 提取到 WideString 并将 write 提取到 TWebBrowser

DelphiInterface<IHTMLElement> diBODY;
OleCheck(diDoc->get_body(&diBODY));

if (diBODY)
    {
    DelphiInterface<IHTMLElement> diHTML;
    OleCheck(diBODY->get_parentElement(&diHTML));

    if (diHTML)
        {
        WideString wsHTML;
        OleCheck(diHTML->get_outerHTML(&wsHTML));

        // And finally use the `Document->write` like above to write into your final TWebBrowser document here...
        }
    }