如何在SQL / PLSQL中读取XMLTYPE数据但命名空间(Oracle)

时间:2018-09-18 17:47:11

标签: xml oracle

我在文件中有这段XML数据

<?xml version="1.0" encoding="UTF-8"?>

-<p:FatturaElettronica xsi:schemaLocation="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2 http://www.fatturapa.gov.it/export/fatturazione/sdi/fatturapa/v1.2/Schema_del_file_xml_FatturaPA_versione_1.2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" versione="FPR12">

这是根标记。现在,我正在尝试提取数据。我正在使用xpath,因为文件更复杂。我可以使用XMLTYPE的EXISTSNODE()EXTRACT()方法成功读取名称空间之前的数据。

现在根标记已更改。我无法处理名称空间。我可以通过将命名空间定义为以下方式来处理数据:

DECLARE
l_ns_def VARCHAR2(240) := 'xmlns:p="http://www.fatturapa.gov.it/sdi/fatturapa/v1.1"';
BEGIN
IF l_xml.EXISTSNODE (l_common_path||'FatturaElettronicaHeader/DatiTrasmissione/IdTrasmittente/IdCodice/text()',l_ns_def) > 0 THEN
l_sender_tic := l_xml.EXTRACT (l_common_path||'FatturaElettronicaHeader/DatiTrasmissione/IdTrasmittente/IdCodice/text()',l_ns_def   ).GETSTRINGVAL ();
EXCEPTION WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(' EOOR - '||SQLERRM);
--END IF;
END;

l_sender_tic使用的变量是VARCHAR2(2000) L_COMMON_PATH = / p:FatturaElettronica 但我现在无法提取数据。该错误是由于绑定数组太小或ORA-30625:不允许在NULL SELF参数上进行方法分派

我猜问题出在根标签上。 FILE具有正确的语法已确认。请帮我解决这个问题。

1 个答案:

答案 0 :(得分:0)

您的代码似乎可以使用您链接到的XML:

DECLARE
  l_xml xmltype := xmltype(q'[<?xml version="1.0" encoding="UTF-8"?>
<p:FatturaElettronica xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:p="http://www.fatturapa.gov.it/sdi/fatturapa/v1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" versione="1.1">
<FatturaElettronicaHeader>
...
</FatturaElettronicaBody>
</p:FatturaElettronica>]');

  l_sender_tic varchar2(4000);
  l_common_path varchar2(30) := '/p:FatturaElettronica/';
  l_ns_def VARCHAR2(240) := 'xmlns:p="http://www.fatturapa.gov.it/sdi/fatturapa/v1.1"';
BEGIN
  IF l_xml.EXISTSNODE (l_common_path||'FatturaElettronicaHeader/DatiTrasmissione/IdTrasmittente/IdCodice/text()',l_ns_def) > 0 THEN
    l_sender_tic := l_xml.EXTRACT (l_common_path||'FatturaElettronicaHeader/DatiTrasmissione/IdTrasmittente/IdCodice/text()',l_ns_def).GETSTRINGVAL ();
  END IF;
  dbms_output.put_line('Got: ' || l_sender_tic);
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE(' EOOR - '||SQLERRM);
END;
/

Got: 01234567890

PL/SQL procedure successfully completed.

如果根节点如您在问题开始时所示那样发生变化,则l_ns_def必须进行更改以匹配:

DECLARE
  l_xml xmltype := xmltype(q'[<?xml version="1.0" encoding="UTF-8"?>
<p:FatturaElettronica xsi:schemaLocation="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2 http://www.fatturapa.gov.it/export/fatturazione/sdi/fatturapa/v1.2/Schema_del_file_xml_FatturaPA_versione_1.2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" versione="FPR12">
<FatturaElettronicaHeader>
...
</FatturaElettronicaBody>
</p:FatturaElettronica>]');

  l_sender_tic varchar2(4000);
  l_common_path varchar2(30) := '/p:FatturaElettronica/';
  l_ns_def VARCHAR2(240) := 'xmlns:p="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2"';
BEGIN
  IF l_xml.EXISTSNODE (l_common_path||'FatturaElettronicaHeader/DatiTrasmissione/IdTrasmittente/IdCodice/text()',l_ns_def) > 0 THEN
    l_sender_tic := l_xml.EXTRACT (l_common_path||'FatturaElettronicaHeader/DatiTrasmissione/IdTrasmittente/IdCodice/text()', l_ns_def).GETSTRINGVAL ();
  END IF;
  dbms_output.put_line('Got: ' || l_sender_tic);
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE(' EOOR - '||SQLERRM);
END;
/

Got: 01234567890

PL/SQL procedure successfully completed.

使用XMLTable一次提取多个数据点的快速示例;假设您的XML文档位于your_table列中的xml中:

select x.*
from your_table t
cross join xmltable(
  xmlnamespaces('http://ivaservizi.agenziaentrate.gov.it/docs/xsd/fatture/v1.2' as "p"),
  '/p:FatturaElettronica'
  passing t.xml
  columns IdPaese varchar2(8) path 'FatturaElettronicaHeader/DatiTrasmissione/IdTrasmittente/IdPaese',
    IdCodice number path 'FatturaElettronicaHeader/DatiTrasmissione/IdTrasmittente/IdCodice',
    CodiceFiscale number path 'FatturaElettronicaHeader/CessionarioCommittente/DatiAnagrafici/CodiceFiscale',
    Data date path 'FatturaElettronicaBody/DatiGenerali/DatiGeneraliDocumento/Data'
) x;

IDPAESE    IDCODICE CODICEFISCALE DATA       
-------- ---------- ------------- -----------
IT       1234567890    9876543210 18-Dec-2014

根据文档结构和要提取的内容,它可能变得更加复杂,但这是基本思想。