我在我的Delphi和.Net C#测试项目中使用WebBrowser控件导航到本地测试XML文件并尝试将内容保存回.Net DocumentCompleted
事件和Delphi中的XML文件onNavigateComple2
事件。
问题是我总是得到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)的问题很难获得特权用户访问。
所以我在这里问你是否知道如何解决我的问题?
提前致谢, 干杯
输入:
<?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"> </SPAN>
<SPAN class="m"><?</SPAN><SPAN class="pi">xml version="1.0" encoding="UTF-8" </SPAN><SPAN class="m">?></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"><</SPAN><SPAN class="t">test</SPAN><SPAN class="m">></SPAN></DIV>
<DIV><DIV class="e"><DIV STYLE="margin-left:1em;text-indent:-2em">
<SPAN class="b"> </SPAN>
<SPAN class="m"><</SPAN><SPAN class="t">data</SPAN><SPAN class="m">></SPAN><SPAN class="tx">xxxx</SPAN><SPAN class="m"></</SPAN><SPAN class="t">data</SPAN><SPAN class="m">></SPAN>
</DIV></DIV>
<DIV><SPAN class="b"> </SPAN>
<SPAN class="m"></</SPAN><SPAN class="t">test</SPAN><SPAN class="m">></SPAN></DIV>
</DIV></DIV>
</BODY>
</HTML>
答案 0 :(得分:4)
我认为你正以错误的方式接近这一点。 TWebBrowser
控件是用于查看的可视控件。您可以从中提取基础数据,但从根本上说,使用可视化控件下载某些内容(非可视化操作)并不是一种好方法。相反,您应该使用专用API下载该文件。
仅供参考:没有 我使用WebClient或Indy的方式 用于访问xml的组件。我也 自...以来无法作为代理播放。
你有没有这些组件?在这种情况下,我建议您使用以下任一方法:
TDownloadURL
是一个内置类,对于简单下载文件很有用。使用它的一些例子:
InternetReadFile。这是我个人在我自己的代码中使用的东西 - 我有一个小的线程类来异步下载文件并在完成后通知主线程,使用这个函数实现。使用它:
INTERNET_FLAG_HYPERLINK or INTERNET_FLAG_NO_UI
标记很抱歉,我无法发布源代码,但它们功能很简单,您应该会发现它很容易编写。
这些方法将获取文件或缓冲区,每个文件或缓冲区都包含XML文件的原始内容。
编辑:我看到你解释了为什么你不能使用Indy:
“真实场景非常复杂 需要在浏览器中进行用户交互 并在用户做了一切之后 之间有一些帖子 浏览器和用户直到最终结果 是一个你没有的XML文件 控制来自哪里!“
我不确定这会阻止你使用Indy:相反,你只需要获取这个XML的位置。你无法控制它的位置并不重要,你只需要找出它的位置。如果您拥有的只是一个链接(您已经可以从浏览器获取HTML - 实际上,这是您的问题!)或者查看TWebBrowser
文档所在的最终位置,并下载该链接,请抓取HTML。换句话说,让用户做他们必须做的任何事情来导航到最终的XML文件,但不是试图从Web浏览器控件中提取它,而是自己下载。
答案 1 :(得分:4)
您可以在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事件发挥作用。