在表中加载XML

时间:2018-09-05 12:11:43

标签: sql oracle xml-parsing

我确实有以下数据:

<EXDATA>
   <FLAG_LIST>
      <FLAG>
         <INST>APPLE</INST>
         <IDENT_LIST>
            <IDET NAME="ID_NUMBER" INST="AMOZ">111111111111</IDET>
            <IDET NAME="ID_PASSPORT" INST="AMOZ">2222222222222</IDET>
         </IDENT_LIST>
         <FLAGYN>0</FLAGYN>
         <EDATA_LIST_REQ>
            <EDATA NAME="NAM">JACKIE</EDATA>
            <EDATA NAME="SURNAME" INSTO="AMOZ">JOHN</EDATA>
         </EDATA_LIST_REQ>
      </FLAG>
       </FLAG_LIST>
</EXDATA>

我尝试通过以下方式将数据插入表中:

select x1.ID_NUMBER,X1.ID_PASSPORT,X2.NAM,x2.SURNAME
   from xml_tab t
      , xmltable(
          '/EXDATA/FLAG_LIST/FLAG/IDENT_LIST' 
          passing t.xml_data
          columns  ID_NUMBER varchar2(100) path 'IDET[1]/text()', 
         ID_PASSPORT number path 'IDET[2]/text()'
               , EDATA_LIST_REQ      xmltype      path 'EDATA_LIST_REQ' 
       ) (+) x1
      , xmltable(
          '/EDATA_LIST_REQ' 
         passing x1.EDATA_LIST_REQ
         columns 
         NAM   VARCHAR2(13) path 'EDATA[1]/text()' ,
           SURNAME VARCHAR2(50) path 'EDATA[2]/text()'
      ) (+) x2

但是没有正确的结果:

ID_NUMBER   ID_PASSPORT    NAME   SURNAME 
111111111   222222222222   NULL    NULL

请帮助。

1 个答案:

答案 0 :(得分:0)

在您的第一个XMLTable调用中,您正在寻找EDATA_LIST_REQ传递给第二个XMLTable调用。但是您正在/EXDATA/FLAG_LIST/FLAG/IDENT_LIST下寻找它。它不是IDENT_LIST的子级,而是同级。因此,您可以使用'./../EDATA_LIST_REQ'更改要遍历的路径:

select x1.ID_NUMBER,X1.ID_PASSPORT,X2.NAM,x2.SURNAME
   from xml_tab t
      , xmltable(
          '/EXDATA/FLAG_LIST/FLAG/IDENT_LIST' 
          passing t.xml_data
          columns  ID_NUMBER varchar2(100) path 'IDET[1]/text()', 
         ID_PASSPORT number path 'IDET[2]/text()'
               , EDATA_LIST_REQ      xmltype      path './../EDATA_LIST_REQ' 
       ) (+) x1
      , xmltable(
          '/EDATA_LIST_REQ' 
         passing x1.EDATA_LIST_REQ
         columns 
         NAM   VARCHAR2(13) path 'EDATA[1]/text()' ,
           SURNAME VARCHAR2(50) path 'EDATA[2]/text()'
      ) (+) x2

或离开该路径并更改其他两个和主要的XPath:

select x1.ID_NUMBER,X1.ID_PASSPORT,X2.NAM,x2.SURNAME
   from xml_tab t
      , xmltable(
          '/EXDATA/FLAG_LIST/FLAG' 
          passing t.xml_data
          columns  ID_NUMBER varchar2(100) path 'IDENT_LIST/IDET[1]/text()', 
         ID_PASSPORT number path 'IDENT_LIST/IDET[2]/text()'
               , EDATA_LIST_REQ      xmltype      path 'EDATA_LIST_REQ' 
       ) (+) x1
      , xmltable(
          '/EDATA_LIST_REQ' 
         passing x1.EDATA_LIST_REQ
         columns 
         NAM   VARCHAR2(13) path 'EDATA[1]/text()' ,
           SURNAME VARCHAR2(50) path 'EDATA[2]/text()'
      ) (+) x2

但是您不需要外部联接,并且在使用XMLTable时不需要显式引用/text();但更麻烦的是您使用[1][2]来引用列表中的特定节点。这似乎是在对数据结构进行假设,这些假设可能无法保证始终是正确的。有了属性名称,使用属性名称会更安全,更清晰。所以我可能会做更多类似的事情:

select x1.id_number, x1.id_passport, x2.nam, x2.surname
from xml_tab t
cross join xmltable (
  '/EXDATA/FLAG_LIST/FLAG' 
  passing t.xml_data
  columns id_number varchar2(100) path 'IDENT_LIST/IDET[@NAME="ID_NUMBER"]', 
          id_passport number      path 'IDENT_LIST/IDET[@NAME="ID_PASSPORT"]',
          edata_list_req xmltype  path 'EDATA_LIST_REQ' 
) x1
cross join xmltable (
  '/EDATA_LIST_REQ' 
  passing x1.edata_list_req
  columns nam varchar2(13)     path 'EDATA[@NAME="NAM"]',
          surname varchar2(50) path 'EDATA[@NAME="SURNAME"]'
) x2

第二个XPath甚至只是'.',尽管重复/EDATA_LIST_REQ并没有什么坏处。

尽管您可能要检查这些数据类型-id_number实际上是数字还是字母数字? varchar2列的长度是否合理?等等