http://www.bankofcanada.ca/stats/assets/rates_RSS/noon/en_all.xml
我正在使用以下相当简单的代码:
var szUrl: string; http: IXMLHTTPRequest; begin szUrl := 'http://www.bankofcanada.ca/stats/assets/rates_RSS/noon/en_all.xml'; http := CoXMLHTTP60.Create; http.open('GET',szUrl,False,'',''); http.send(EmptyParam); Assert(http.Status = 200); Memo1.Lines.Add('HTTP/1.1 '+IntToStr(http.status)+' '+http.statusText); Memo1.Lines.Add(http.getAllResponseHeaders); Memo1.Lines.Add(http.responseText);
我不会显示返回的所有正文,但它会在responseText中返回有效的xml:
HTTP/1.1 200 OK Cache-Control: max-age=5 Connection: keep-alive Connection: Transfer-Encoding Date: Fri,30 Mar 2012 14:50:50 GMT Transfer-Encoding: chunked Content-Type: text/html; charset=UTF-8 Expires: Fri,30 Mar 2012 14:50:55 GMT Server: Apache/2.2.16 (Unix) PHP/5.3.3 mod_ssl/2.2.16 OpenSSL/1.0.0d mod_perl/2.0.4 Perl/v5.12.0 X-Powered-By: PHP/5.3.3 <?xml version="1.0" encoding="ISO-8859-1"?> <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-Syntax-ns#" xmlns="http://purl.org/RSS/1.0/" xmlns:cb="http://www.cbwiki.net/wiki/index.PHP/Specification_1.1" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3c.org/1999/02/22-rdf-Syntax-ns#rdf.xsd"> <channel rdf:about="http://www.bankofcanada.ca/stats/assets/rates_RSS/noon/en_ALL.xml"> <title xml:lang="en">Bank of Canada: Noon Foreign Exchange Rates</title> <link>http://www.bankofcanada.ca/rates/exchange/noon-rates-5-day/</link>
好的,很好,那里有有效的xml.我知道这是有效的,因为……好好看看它.但我也知道通过解析它是有效的:
var ... szXml: WideString; doc: DOMDocument60; begin ... szXml := http.responseText; doc.loadXML(szXml); Assert(doc.parseError.errorCode = 0); Memo1.Lines.Add('============parsed xml'); Memo1.Lines.Add(doc.xml);
原始IXmlHttpRequest
包含responseXml
财产.来自MSDN:
Represents the parsed response entity body.
If the response entity body is not valid XML,this property returns DOMDocument that was parsed so that you can access the error. This property does not return IXMLDOMParseError itself,but it is accessible from DOMDocument.
在我的情况下,responseXml属性存在,因为它应该:
Assert(http.responseXml <> nil);
并且没有responseText的解析错误:
doc := http.responseXml as DOMDocument60; Assert(doc.parseError.errorCode = 0);
应该有,因为xml是有效的.
除了当我查看http.responseXml文档对象时,它是空的:
Memo1.Lines.Add('============responseXml'); Memo1.Lines.Add(doc.xml);
是时IXMLHttpRequest(和IXMLServerHttpRequest)返回一个空的XML文档,时间为:
>有xml
> xml有效
>没有解析错误
长形式:
uses msxml2_tlb; procedure TForm1.Button1Click(Sender: TObject); var szUrl: string; http: IXMLHTTPRequest; doc: DOMDocument60; begin szUrl := 'http://www.bankofcanada.ca/stats/assets/rates_RSS/noon/en_all.xml'; http := CoXMLHTTP60.Create; //or CoServerXmlHttpRequest.Create http.open('GET',''); http.send(EmptyParam); Assert(http.Status = 200); doc := http.responseXml as DOMDocument60; Assert(doc.parseError.errorCode = 0); ShowMessage('"'+doc.xml+'"'); end;
我如何使XmlHttpRequest
(更重要的是ServerXMLHTTP60
)表现得像记录的那样?
我用Fiddler将http响应保存到文本文件中.之后我可以修改响应文件,并指示fiddler提供我手工制作的替代品,而不是去原始的网站.
经过3个小时的摆弄,我设法在原始的http响应标头中追踪问题:
HTTP/1.1 200 OK Cache-Control: max-age=5 Connection: keep-alive Connection: Transfer-Encoding Date: Fri,30 Mar 2012 14:50:55 GMT Server: Apache/2.2.16 (Unix) PHP/5.3.3 mod_ssl/2.2.16 OpenSSL/1.0.0d mod_perl/2.0.4 Perl/v5.12.0 X-Powered-By: PHP/5.3.3
应该:
HTTP/1.1 200 OK Cache-Control: max-age=5 Connection: keep-alive Connection: Transfer-Encoding Date: Fri,30 Mar 2012 14:50:50 GMT Transfer-Encoding: chunked Content-Type: text/xml; charset=UTF-8 Expires: Fri,30 Mar 2012 14:50:55 GMT Server: Apache/2.2.16 (Unix) PHP/5.3.3 mod_ssl/2.2.16 OpenSSL/1.0.0d mod_perl/2.0.4 Perl/v5.12.0 X-Powered-By: PHP/5.3.3
一旦我发现问题,我就能找回the documentation that explain the behavior:
The supported MIME types for MSXML 6.0 are:
- “text/xml“
- “application/xml“
- or anything that ends with “+xml“,for example “application/RSS+xml“
我正在提取的RSS源实际上是Resource Definition Format (RDF) feed,其中内容类型应该是:
application/rdf+xml
他们的用途:
text/html
这么多级别都是错的.
所以我所经历的行为是设计的;虽然令人沮丧 – 因为没有简单的方法来知道responseXml是否“有效”.
>将分配responseXml对象>将分配parseError对象> parseError.ErrorCode为零> responseXml.documentElement将为nil