如何从WebBrowser控件获取XML(RAW / SOURCE)

我在我的Delphi和.Net C#测试项目中使用WebBrowser控件导航到本地测试XML文件,并尝试将内容保存回.Net DocumentCompleted Event和Delphi onNavigateComple2事件中的XML文件。

问题是我总是得到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代码我可以显示SOURCE的工作原理(这意味着源代码在那里)但是我不能使用它,因为它会播放一个对话框并且不容易获取数据并关闭该对话框(在我的测试用例中)我得到带有我的xml内容的notepad.exe)

  AWebBrowser.Document.QueryInterface(IOleCommandTarget, CmdTarget) ; if CmdTarget  nil then try CmdTarget.Exec(PtrGUID, HTMLID_VIEWSOURCE, 0, vaIn, vaOut) ; finally CmdTarget._Release; end; 

我还设法用xxx-HIDE-xxx标志调用SAVE AS调用,但是它将IE 5连接起来,因为对话框将被显示(隐藏标志将被忽略)。

我还尝试从缓存中获取XML数据(缓存API)但在我的情况下我不会得到任何东西2.如果在客户机器上缓存被禁用怎么办? 😉

InnerText或InnerHTML atc。 不能使用,因为它们包含 – 和+ char并且不代表原始RAW数据(SOURCE)

仅供参考:我无法使用WebClient或Indy组件访问xml。 我也无法作为代理播放,因为在客户机器上打开端口(比如8080)的问题是特权用户访问的痛苦。

所以我在这里问你是否知道如何解决我的问题?

提前谢谢,干杯

输入:

  xxxx 

输出:

  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}   
  <?xml version="1.0" encoding="UTF-8" ?>
- <test>
  <data>xxxx</data>
  </test>

我认为你接近这个错误的方式。 TWebBrowser控件是一种用于查看的可视控件。 您可以从中提取基础数据,但从根本上说,使用可视化控件下载某些内容(非可视化操作)并不是一种好方法。 相反,您应该使用专用API下载该文件。

仅供参考:我无法使用WebClient或Indy组件访问xml。 我也不能作为代理人玩…

你有这些组件吗? 在这种情况下,我建议您使用以下任一方法:

  1. TDownloadURL是一个内置类,对于简单下载文件很有用。 使用它的一些例子:

    • HTML页面刮刀 – 显然也适用于XML
    • 如何在下载时显示进度指示器 – 如果文件很小,可能没用
  2. InternetReadFile 。 这是我个人在我自己的代码中使用的 – 我有一个小的线程类来异步下载文件并在完成后通知主线程,使用此函数实现。 使用它:

    • 使用InternetOpen初始化互联网function的使用; 它返回一个句柄;
    • 使用该句柄使用INTERNET_FLAG_HYPERLINK or INTERNET_FLAG_NO_UI标志使用InternetOpenUrl获取另一个句柄
    • 然后在循环写入缓冲区时使用带有InternetReadFile的句柄,直到读取文件或终止线程。
    • 不要忘记使用InternetCloseHandle关闭句柄

    对不起,我无法发布源代码,但它们是简单的function,您应该发现它很容易编写。

这些方法将获取文件或缓冲区,每个文件或缓冲区都包含XML文件的原始内容。

编辑:我看到你解释了为什么你不能使用Indy:

“真实场景非常复杂,需要在浏览器中进行用户交互,在用户完成所有操作后,浏览器和用户之间会有一些post,直到最终结果是一个XML文件,你无法控制它来自哪里!”

我不确定这会阻止你使用Indy:相反,你只需要获取这个XML的位置。 你无法控制它的位置并不重要,你只需要找出它的位置。 如果您拥有的只是一个链接(您已经可以从浏览器获取HTML – 事实上,那就是您的问题!)或者查看TWebBrowser文档所在的最终位置,并下载它。 换句话说,让用户做他们必须做的任何事情来导航到最终的XML文件,但不是试图从Web浏览器控件中提取它,而是自己下载。

您可以在TWebBrowser BeforeNavigate2事件中对文件进行“阴影”下载。
通过阴影,我的意思是使用来自另一个库的过程来下载文件,同时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事件工作。