0

我正在尝试从 plsql 调用网络服务。我有以下代码(有效):

CREATE OR REPLACE PROCEDURE WEBSERVICE AS
    v_xml XMLTYPE;
BEGIN
    v_xml := XMLTYPE(UTL_HTTP.REQUEST(URL => 'http://dev.markitondemand.com/Api/Quote?symbol=AAPL'));
    FOR x IN (SELECT
        EXTRACTVALUE(VALUE(p), '/Data/Status/text()') AS title
    FROM TABLE(XMLSEQUENCE(EXTRACT(v_xml, '/QuoteApiModel/Data'))) p)
    LOOP
        DBMS_OUTPUT.PUT_LINE(x.title);
    END LOOP;
    COMMIT;
END;

但是这段代码不起作用:

CREATE OR REPLACE PROCEDURE WEBSERVICE AS
    v_xml XMLTYPE;
BEGIN
    v_xml := XMLTYPE(UTL_HTTP.REQUEST(URL => 'http://xkcd.com/rss.xml'));
    FOR x IN (SELECT
        EXTRACTVALUE(VALUE(p), 'item/title/text()') AS title
    FROM TABLE(XMLSEQUENCE(EXTRACT(v_xml, '/rss/channel/item'))) p)
    LOOP
        DBMS_OUTPUT.PUT_LINE(x.title);
    END LOOP;
    COMMIT;
END;

它给了我以下错误:

Connecting to the database oracle.
ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML processing
LPX-00007: unexpected end-of-file encountered
ORA-06512: at "SYS.XMLTYPE", line 310
ORA-06512: at "SYS.WEBSERVICE", line 4
ORA-06512: at line 2
Process exited.
Disconnecting from the database oracle.

我注意到的不同之处在于 xkcd rss 提要有一个 xml 标头,而另一个则没有。我应该怎么做才能完成这项工作?

4

1 回答 1

0

没错,由于 XML 标头的存在而发生错误。

解决方法是用来XMLParse(document ...)解析 XML:

select xmlparse(document UTL_HTTP.REQUEST(URL => 'http://xkcd.com/rss.xml')) 
into v_xml 
from dual;

带有来自 xkcd.com 的结果的示例SQLFiddle。

请注意,根据文档 HTTP_UTIL.Request功能,仅返回服务器响应的前 2000 个字节,因此您可以通过此类请求获得不完整的 XML。

更新

从 XML 中提取值的更优雅的方法是使用XMLTable()带有XQuery的函数:

FOR x IN (

  select title
  from 
    XMLTable(
      'for $i in $p/rss/channel/item/title return $i'
      passing 
        XMLParse(document UTL_HTTP.REQUEST(URL => '...')) as "p"
      columns 
        title varchar2(4000) path '//title'
    )

)  
LOOP
    DBMS_OUTPUT.PUT_LINE(x.title);
END LOOP;

SQLFiddle

至少,这种方法允许您为不同的 RSS 源创建更灵活的选项。

于 2013-06-20T12:26:01.337 回答