如何从WebBrowser控件中获取XMLRAW / SOURCE

问题描述

|| 我在Delphi和.Net C#测试项目中都使用Webbrowser控件导航到本地测试XML文件,并尝试将内容保存回.Net
DocumentCompleted
事件和Delphi
onNavigateComple2
事件中的XML文件。 问题是我总是得到HTML,HTML将由浏览器转换成HTML以供查看(检查我的输出:我使用以下代码保存了它)
procedure TForm1.SaveHTMLSourcetoFile(const FileName: string;
  WB: TWebbrowser);
var
  PersistStream: IPersistStreamInit;
  FileStream: TFileStream;
  Stream: IStream;
  SaveResult: HRESULT;
begin
  PersistStream := WB.Document as IPersistStreamInit;
  FileStream := TFileStream.Create(FileName,fmCreate);
  try
    Stream := TStreamAdapter.Create(FileStream,soReference) as IStream;
    SaveResult := PersistStream.Save(Stream,True);
    if Failed(SaveResult) then
      MessageBox(Handle,\'Fail to save source\',\'Error\',0);
  finally
    FileStream.Free;
  end;
end;
好吧,我已经尝试了几乎所有内容,在所有地方都进行了搜索,但是直到现在都找不到有用的东西。在下面的Delphi代码中,我试图显示有效的源(这意味着源位于此处),但是我无法使用它,因为它将播出一个对话框并且不容易获取数据并关闭该对话框(在我的测试案例中)我得到带有XML内容的notepad.exe)
  AWebbrowser.Document.QueryInterface(IOleCommandTarget,CmdTarget) ;
  if CmdTarget <> nil then
  try
    CmdTarget.Exec(PtrGUID,HTMLID_VIEWSOURCE,vaIn,vaOut) ;
  finally
    CmdTarget._Release;
  end;
我还设法使用xxx-HIDE-xxx标志调用SAVE AS调用,但是它接缝了IE 5,将显示“另存为”对话框(将忽略hide标志)。 我还尝试从缓存(Cache API)获取XML数据,但是在我的情况下我什么也得不到。2.如果在客户计算机上禁用了缓存,该怎么办? ;-) InnerText或InnerHTML atc。无法使用,因为它们包含-和+ char且不代表原始的RAW数据(源) 仅供参考:我无法使用WebClient或Indy组件来访问xml。我也不能充当代理,因为在客户计算机上打开端口(比如说8080)的问题使特权用户访问感到痛苦。 所以我在这里,问你是否有解决我的问题的想法? 提前致谢, 干杯 输入:
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<test><data>xxxx</data></test>
输出
<HTML><HEAD>
<STYLE>BODY{font:x-small \'Verdana\';margin-right:1.5em}
.c{cursor:hand}
.b{color:red;font-family:\'Courier New\';font-weight:bold;text-decoration:none}
.e{margin-left:1em;text-indent:-1em;margin-right:1em}
.k{margin-left:1em;text-indent:-1em;margin-right:1em}
.t{color:#990000}
.xt{color:#990099}
.ns{color:red}
.dt{color:green}
.m{color:blue}
.tx{font-weight:bold}
.db{text-indent:0px;margin-left:1em;margin-top:0px;margin-bottom:0px;padding-left:.3em;border-left:1px solid #CCCCCC;font:small Courier}
.di{font:small Courier}
.d{color:blue}
.pi{color:blue}
.cb{text-indent:0px;margin-left:1em;margin-top:0px;margin-bottom:0px;padding-left:.3em;font:small Courier;color:#888888}
.ci{font:small Courier;color:#888888}
PRE{margin:0px;display:inline}</STYLE>
<SCRIPT><!--
function f(e){
if (e.className==\"ci\"){if (e.children(0).innerText.indexOf(\"\\n\")>0) fix(e,\"cb\");}
if (e.className==\"di\"){if (e.children(0).innerText.indexOf(\"\\n\")>0) fix(e,\"db\");}
e.id=\"\";
}
function fix(e,cl){
e.className=cl;
e.style.display=\"block\";
j=e.parentElement.children(0);
j.className=\"c\";
k=j.children(0);
k.style.visibility=\"visible\";
k.href=\"#\";
}
function ch(e){
mark=e.children(0).children(0);
if (mark.innerText==\"+\"){
mark.innerText=\"-\";
for (var i=1;i<e.children.length;i++)
e.children(i).style.display=\"block\";
}
else if (mark.innerText==\"-\"){
mark.innerText=\"+\";
for (var i=1;i<e.children.length;i++)
e.children(i).style.display=\"none\";
}}
function ch2(e){
mark=e.children(0).children(0);
contents=e.children(1);
if (mark.innerText==\"+\"){
mark.innerText=\"-\";
if (contents.className==\"db\"||contents.className==\"cb\")
contents.style.display=\"block\";
else contents.style.display=\"inline\";
}
else if (mark.innerText==\"-\"){
mark.innerText=\"+\";
contents.style.display=\"none\";
}}
function cl(){
e=window.event.srcElement;
if (e.className!=\"c\"){e=e.parentElement;if (e.className!=\"c\"){return;}}
e=e.parentElement;
if (e.className==\"e\") ch(e);
if (e.className==\"k\") ch2(e);
}
function ex(){}
function h(){window.status=\" \";}
document.onclick=cl;
--></SCRIPT>
</HEAD>
<BODY class=\"st\"><DIV class=\"e\">
<SPAN class=\"b\">&nbsp;</SPAN>
<SPAN class=\"m\">&lt;?</SPAN><SPAN class=\"pi\">xml version=\"1.0\" encoding=\"UTF-8\" </SPAN><SPAN class=\"m\">?&gt;</SPAN>
</DIV>
<DIV class=\"e\">
<DIV class=\"c\" STYLE=\"margin-left:1em;text-indent:-2em\"><A href=\"#\" onclick=\"return false\" onfocus=\"h()\" class=\"b\">-</A>
<SPAN class=\"m\">&lt;</SPAN><SPAN class=\"t\">test</SPAN><SPAN class=\"m\">&gt;</SPAN></DIV>
<DIV><DIV class=\"e\"><DIV STYLE=\"margin-left:1em;text-indent:-2em\">
<SPAN class=\"b\">&nbsp;</SPAN>
<SPAN class=\"m\">&lt;</SPAN><SPAN class=\"t\">data</SPAN><SPAN class=\"m\">&gt;</SPAN><SPAN class=\"tx\">xxxx</SPAN><SPAN class=\"m\">&lt;/</SPAN><SPAN class=\"t\">data</SPAN><SPAN class=\"m\">&gt;</SPAN>
</DIV></DIV>
<DIV><SPAN class=\"b\">&nbsp;</SPAN>
<SPAN class=\"m\">&lt;/</SPAN><SPAN class=\"t\">test</SPAN><SPAN class=\"m\">&gt;</SPAN></DIV>
</DIV></DIV>
</BODY>
</HTML>
    

解决方法

我认为您正在采用错误的方式。 “ 6”控件是用于查看的视觉控件。您也许可以从中提取基础数据,但是从根本上讲,使用可视化控件下载某些内容(非可视化操作)不是一个好方法。相反,您应该使用专用的API下载文件。   仅供参考:没有   我使用WebClient或Indy的方式   组件以访问xml。我也   不能充当代理,因为... 您没有那些成分吗?在这种情况下,建议您使用以下两种方法之一:
TDownloadURL
是一个内置类,对于简单下载文件很有用。一些使用它的例子: HTML页面抓取器-显然也适用于XML 下载时如何显示进度指示器-如果文件很小,可能无用 InternetReadFile。这就是我个人在自己的代码中使用的-我有一个小线程类,用于异步下载文件并在完成后通知主线程,使用此功能即可实现。使用方式: 使用InternetOpen初始化对Internet功能的使用;它返回一个句柄; 使用该句柄使用带有
INTERNET_FLAG_HYPERLINK or INTERNET_FLAG_NO_UI
标志的InternetOpenUrl获取另一个句柄 然后在写入缓冲区的循环中使用该句柄和InternetReadFile,直到读取文件或终止线程。 不要忘记使用InternetCloseHandle关闭句柄 抱歉,我无法发布源代码,但是它们是简单的函数,您应该会发现它很容易编写。 这些方法将获取文件或缓冲区,每个文件或缓冲区均包含XML文件的原始内容。 编辑:我看到你解释了为什么不能使用Indy的一些解释:   “实际情况非常复杂,   需要浏览器中的用户交互   在用户完成所有操作之后   之间有一些帖子   浏览器和用户直到最终结果   是您没有的XML文件   控制来自哪里!\“ 我不确定这会阻止您使用Indy:相反,您只需要获取此XML的位置即可。您不控制它在哪里的事实并不重要,您只需要找出它在哪里。如果只有链接,则抓取HTML(您已经可以从浏览器中获取HTML-实际上,这就是您的问题!),或者查看
TWebBrowser
文档所在的最终位置,然后下载该文件。换句话说,让用户执行导航到最终XML文件所需的所有操作,而不是尝试从Web浏览器控件中提取文件,而是自己下载。     ,您可以在TWebBrowser BeforeNavigate2事件中“ \ shadow \”下载文件。 影子,我的意思是在TWebBrowser下载文件的同时,使用另一个库中的过程下载文件。这样,您可以获取文件而无需TWebBrowser对其进行修改。 我写了一个测试应用程序,我要做的就是获取文件内容
procedure TForm1.WebBrowserBeforeNavigate2(Sender: TObject;
  const pDisp: IDispatch; var URL,Flags,TargetFrameName,PostData,Headers: OleVariant; var Cancel: WordBool);
begin
  HttpGetText(URL,Memo1.Lines);
end;
HttpGetText是Synapse库http://www.ararat.cz/synapse/doku.php/start中的阻止函数 您也可以使用ICS,Indy或TDownLoadURL。请注意,TDownLoadURL没有被阻止,并且我无法使其AfterDownload事件正常工作。