【问题标题】:Oracle xmltable parsing return LPX-00209Oracle xmltable 解析返回 LPX-00209
【发布时间】:2017-06-01 07:22:58
【问题描述】:

我是 Oracle 的新手。现在我正在尝试解析 XML 并将其放入 VK_ACCOUNTS 表中。 我的 xml 示例在这里:

<?xml version="1.0" encoding="utf-8"?>
<response list="true">
 <account>
  <account_id>1656672360</account_id>
  <account_type>general</account_type>
  <account_status>1</account_status>
  <access_role>reports</access_role>
 </account>
</response>

我请求具有以下功能的 xml,据我所知,它正确返回了 xml:

create or replace function GET_CLOBFROMURL(
  p_url     varchar2,
  p_charset varchar2 default 'UTF8'
) return clob
is
  req   utl_http.req; 
  resp  utl_http.resp;
  val   varchar2(32547);
  a     clob;
BEGIN
  a:='';
  dbms_lob.createtemporary(a,true);
  dbms_lob.open(a,dbms_lob.lob_readwrite);
  req := utl_http.begin_request(p_url);
  utl_http.set_body_charset(req, p_charset);
  resp := utl_http.get_response(req);
  LOOP
    a := a||val;
    utl_http.read_text(resp, val, 5000);
  END LOOP;
  utl_http.end_response(resp);
  return a;
EXCEPTION
  WHEN utl_http.end_of_body THEN
    utl_http.end_response(resp);
    return a;
  WHEN others then
    utl_http.end_response(resp);
    raise;
END;

并获取 xml 到 xml_clob

xml_clob := tableau.get_clobFromUrl(REQUEST);
    IF xml_clob != EMPTY_CLOB() THEN
    insert into tableau.VK_ACCOUNTS(account_id, account_type, account_status, access_role)
        SELECT
        proc.account_id,
        proc.account_type,
        proc.account_status,
        proc.access_role   
        FROM XMLTABLE('response/account' passing (select xmltype(xml_clob)  resp FROM dual)
            columns account_id number             path '/account/account_id',
                    account_type varchar2(20)     path '/account/account_type',
                    account_status number         path '/account/account_status',
                    access_role varchar2(20)      path '/account/access_role'
                ) proc;
      COMMIT;     
    END IF;
END;

最后我得到一个错误:

ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML
LPX-00209: PI names starting with XML are reserved
Error at line 3
ORA-06512: на  "SYS.XMLTYPE", line 272
ORA-06512: на  line 1
ORA-06512: на  "TABLEAU.VK_LOADDATA", line 11
ORA-06512: на  line 2

我已经尝试过用于 XML 的 TRIM 函数,但它对我没有帮助。

有什么想法吗?

【问题讨论】:

  • 我不熟悉Oracle,但我想你应该尝试将xml_clob重命名为clob_xml
  • 嗨@Andersson,谢谢,但据我所知,这只是变量的命名,我可以在很小的限制下随意命名。没有?
  • 这是一个简单的建议:我刚刚检查了异常日志中的行names starting with XML are reserved
  • 检查过,不工作:( thx
  • 为什么要获得 CLOB?为什么不为 URL 声明一个 httpuritype 变量并使用它的 GETXML() 方法呢? [docs.oracle.com/cd/E11882_01/appdev.112/e23094/…(XMLDB 开发人员指南)中的示例

标签: oracle xpath oracle11g xml-parsing xmltable


【解决方案1】:
LPX-00209: PI names starting with XML are reserved

当 XML 字符串中有前导空白字符时会发生这种情况。 See http://oraclequirks.blogspot.co.uk/2013/03/lpx-00209-pi-names-starting-with-xml.html.

您应该可以使用以下方法解决它:

XMLType( TRIM( xml_clob ) )

稍微简化你的功能:

create or replace function GET_CLOBFROMURL(
  p_url     varchar2,
  p_charset varchar2 default 'UTF8'
) return clob
is
  req   utl_http.req; 
  resp  utl_http.resp;
  val   varchar2(32547);
  a     clob    := EMPTY_CLOB();
BEGIN
  req := utl_http.begin_request(p_url);
  utl_http.set_body_charset(req, p_charset);
  resp := utl_http.get_response(req);
  LOOP
    BEGIN
      utl_http.read_text(resp, val, 5000);
      a := a||val;
    EXCEPTION
      WHEN utl_http.end_of_body THEN
        utl_http.end_response(resp);
        EXIT;
    END;
  END LOOP;
  return a;
EXCEPTION
  WHEN others THEN
    utl_http.end_response(resp);
    RAISE;
END;

那么插入可以完全在SQL中完成:

insert into tableau.VK_ACCOUNTS (
  account_id,
  account_type,
  account_status,
  access_role
)
SELECT proc.account_id,
       proc.account_type,
       proc.account_status,
       proc.access_role   
FROM   ( SELECT tableau.get_clobFromUrl(REQUEST) AS xml FROM DUAL ) c,
       XMLTABLE(
         '/response/account'
          passing XMLType( TRIM( c.xml ) )
          columns account_id     number       path './account_id',
                  account_type   varchar2(20) path './account_type',
                  account_status number       path './account_status',
                  access_role    varchar2(20) path './access_role'
            ) proc
WHERE  c.xml IS NOT NULL
AND    DBMS_LOB.GETLENGTH( c.xml ) > 0;

【讨论】:

  • 是的,我也阅读了第一行并且已经对其进行了修整。 smth 仍然无法处理相同的错误。
【解决方案2】:

它应该像这样工作

xml_clob := tableau.Get_Clobfromurl(); s := SUBSTR(xml_clob,INSTR(xml_clob,'<'));

【讨论】:

    【解决方案3】:

    我知道重复此异常的 3 种方法。

    1. Prolog 在 xml 中存在不止一次。

    select xmltype('&lt;?xml version="1.0" ?&gt;&lt;?xml version="1.0" ?&gt;&lt;a&gt;&lt;/a&gt;') from dual;

    1. Prolog 不是 xml 的第一个元素。 .

    select xmltype('&lt;a&gt;&lt;/a&gt;&lt;?xml version="1.0" ?&gt;') from dual;

    1. 同样的情况,但这里 xml 的第一行是空的。

    select xmltype(chr(10)||chr(13)||'&lt;?xml version="1.0" ?&gt;&lt;a&gt;&lt;/a&gt;') from dual;

    我认为您面临的问题没有。 3.快速摆脱空第一行的方法。鲜为人知的函数形式TRIM

    select xmltype( trim(leading chr(13) from trim(leading chr(10) from trim(' '||chr(10)||chr(13)||' &lt;?xml version="1.0" ?&gt;&lt;a&gt;&lt;/a&gt;')))) from dual;

    trim(leading chr(13) from trim(leading chr(10) from trim('your_xml_clob')))

    【讨论】:

    • 修改代码的相同错误 FROM XMLTABLE('response/account' 传递 (select xmltype( trim(leading chr(13) from trim(leading chr(10) from trim(' '||chr( 10)||chr(13)||' ')))) from dual) columns account_id number path '/account/account_id', account_type varchar2( 20) 路径'/account/account_type',
    • 看来你是对的,因为我已经尝试过 getClob 函数(它有效)和 getXML 函数(它引发错误)。问题在于 xml,但找出问题所在的更好方法是什么
    • select xmltype(trim(leading chr(13) from trim(leading chr(10) from trim(xml_clob)))) resp FROM dual 你在你的代码中这样做了吗?
    • 是的,我已将 select xmltype(xml_clob) 从原始代码编辑到您的行。
    • 我认为没有。 Oracle 期望 PI( 在文档的第一行。如果此元素在第一行中存在多次或不存在,则会引发错误。
    猜你喜欢
    • 2021-06-16
    • 2017-04-13
    • 2019-01-13
    • 2020-04-29
    • 2014-08-14
    • 2018-08-24
    • 1970-01-01
    • 2017-12-06
    • 2020-03-10
    相关资源
    最近更新 更多