2011-05-26 56 views
9

我在Delphi和.Net C#测试项目中使用WebBrowser控件导航到本地测试XML文件并尝试将内容保存回XML文件在.Net DocumentCompleted事件和德尔福onNavigateComple2事件。如何从WebBrowser控件获取XML(RAW/SOURCE)

的问题是,我总是得到的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, 0, vaIn, vaOut) ; 
    finally 
    CmdTarget._Release; 
    end; 

我也设法调用SAVE AS呼叫与XXX-HIDE-XXX标志,但它接缝了IE 5另存为对话框将显示(隐藏标志将被忽略)。

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

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

仅供参考:我无法使用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> 
+0

等待 - *为什么*你不能直接用WebClient或Indy下载文件?看起来这些应该比涉及巨大的UI控制更简单。 – 2011-05-26 17:08:51

+0

好吧,这只是我在这里发布的一个示例。我写了那个测试xml /测试应用程序。真正的场景非常复杂,需要用户在浏览器中进行交互,并且在用户完成浏览器和用户之间的所有内容后,直到最终结果是一个XML文件,您无法控制哪里来自哪里!这就是为什么! – Gohlool 2011-05-26 21:10:33

回答

4

我觉得你这个接近走错了路。 A TWebBrowser控件是用于查看的视觉控件。您可能能够从中提取底层数据,但从根本上说,使用可视化控件下载某些内容(非视觉操作)不是一种好方法。相反,您应该使用专用的API下载文件。

只是为了您的信息:没有 办法,我使用Web客户端或印 组件访问XML。我也 不能作为一个代理服务器,因为...

难道你没有这些组件?在这种情况下,我建议您使用以下方法:

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

  2. InternetReadFile可能没有用处。这是我个人在我自己的代码中使用的 - 我有一个小的线程类来异步下载文件并在完成时通知主线程,使用此函数实现。使用它:

    • 使用InternetOpen初始化使用互联网功能;它返回一个句柄;
    • 使用该句柄使用InternetOpenUrl使用INTERNET_FLAG_HYPERLINK or INTERNET_FLAG_NO_UI标志
    • 然后使用一个循环的写作与处理InternetReadFile一个缓冲区,直到该文件被读取或者您的线程终止得到另一个手柄。
    • 不要忘记使用InternetCloseHandle

    对不起,我不能发布的源代码以关闭句柄,但他们简单的功能,你会发现它很容易的编写。

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

编辑:我看你解释了一下为什么你不能使用印:

“真正的情况是在浏览器中 并且在用户做了很多复杂和 需要用户交互所有内容 在 浏览器和用户之间有一些帖子帖子,直到最终结果 是一个XML文件,你没有 控制哪里来的!

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

+0

感谢您的评论哥们,并试图指出另一种方法!我知道你在这里写下的每个电话和方法!我无法知道最终的URL是什么!服务器的结果(响应)基于用户的输入/操作,这些输入/操作全部由登录和身份验证处理,并为主要操作输入PIN!这意味着用户在web-From(发布到服务器)中输入一个PIN,根据PIN条目(从不相同且确切的响应)产生响应。 – Gohlool 2011-05-27 00:42:30

+0

@ Gohlool:你确定“没有办法...知道最终的URL是什么”?使用其导航事件之一,您无法看到Web浏览器正在导航到哪里? – 2011-05-31 04:55:21

4

您可以在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是从突触库http://www.ararat.cz/synapse/doku.php/start

你也可以使用ICS,印地被卡死或TDownLoadURL。请注意,TDownLoadURL不会阻塞,我永远无法使其AfterDownload事件正常工作。

+0

谢谢!非常好的主意!但是...以及我的示例上面的工作,但不是在我的真正的应用程序结合服务器! ;-(但你得到了我的投票!;-) – Gohlool 2011-05-29 08:45:06

+0

@ Gohlool-我的方法假设有一个链接到TWebBrowser显示的页面中的XML文件,并且用户点击它。从你的回答中,我必须假设你不是这样。所以我的问题是:你怎么知道XML文件已准备好下载,你如何得到它的地址? – crefird 2011-05-29 17:31:13