Oracle XML:跳过不存在节点

时间:2013-09-03 04:00:37

标签: xml oracle plsql

我有一个问题是将xml数据插入到oracle表中,这里是我的xml:

<begin>
    <entry>
        <lastname>gordon</lastname>
        <NumberList>
            <number>100</number>
            <codelist>
                 <code>213</code>
            <codelist>
        <NumberList>
        <address>
            <addresslist>Jl. jalan pelan-pelan ke Bekasi, Indonesia</addresslist>
        </address>
    </entry>
    <entry>
        <lastname>mark</lastname>
        <address>
            <addresslist>Jl. jalan cepet-cepet ke Jakarta, Indonesia</addresslist>
        </address>
    </entry>
</begin>

我期望的结果是:

LastName | Number | code    | address
gordon   | 100    | 213     |Jl. jalan pelan-pelan ke Bekasi, Indonesia
mark     | Null   | Null    |Jl. jalan cepet-cepet ke Jakarta, Indonesia

当访问不存在的节点时,不会出现1行数据(如第二行数据)。

更新: 这是我目前的代码

 DECLARE
       X XMLTYPE := XMLTYPE('
<begin>
    <entry>
        <lastname>gordon</lastname>
        <NumberList>
            <number>100</number>
            <codelist>
                 <code>213</code>
            </codelist>
        </NumberList>
        <address>
            <addresslist>Jl. jalan pelan-pelan ke Bekasi, Indonesia</addresslist>
        </address>
    </entry>
    <entry>
        <lastname>mark</lastname>
        <address>
            <addresslist>Jl. jalan cepet-cepet ke Jakarta, Indonesia</addresslist>
        </address>
    </entry>
</begin>');
    BEGIN
       FOR R IN (SELECT EXTRACTVALUE(VALUE(P), '/entry/lastname/text()') AS lastname,
                        EXTRACTVALUE(VALUE(P), '/entry/address/addresslist/text()') AS address,
                        EXTRACT(VALUE(P), '/entry/NumberList') AS NumberList
                   FROM TABLE(XMLSEQUENCE(EXTRACT(X, '//begin/entry'))) P)
       LOOP
          FOR R1 IN (SELECT EXTRACTVALUE(VALUE(T1), 'NumberList/number/text()') AS numbers,
                        EXTRACTVALUE(VALUE(T1), 'NumberList/codelist/code/text()') AS code
                       FROM TABLE(XMLSEQUENCE(EXTRACT(R.NumberList, '/NumberList'))) T1)
          LOOP
             DBMS_OUTPUT.PUT_LINE(r.lastname||' | '||R1.numbers||' | '||R1.code||' | '||r.address);
          END LOOP;
       END LOOP;
    END;

2 个答案:

答案 0 :(得分:2)

你没有说你是如何尝试parsexml的。以下是XMLTABLE的示例,它为您提供了例外结果:

with xmldata(d) as (select xmltype('<begin>
    <entry>
        <lastname>gordon</lastname>
        <NumberList>
            <number>100</number>
            <codelist>
                 <code>213</code>
            </codelist>
        </NumberList>
        <address>
            <addresslist>Jl. jalan pelan-pelan ke Bekasi, Indonesia</addresslist>
        </address>
    </entry>
    <entry>
        <lastname>mark</lastname>
        <address>
            <addresslist>Jl. jalan cepet-cepet ke Jakarta, Indonesia</addresslist>
        </address>
    </entry>
</begin>') from dual
)
select x.*
from xmldata,
     xmltable('begin/entry' passing xmldata.d
              columns
              last_name varchar2(10) path 'lastname',
              number_ number path 'NumberList/number',
              code number path 'NumberList/codelist/code',
              address varchar2(50) path 'address/addresslist'
     ) x
;

结果:

LAST_NAME  NUMBER_  CODE ADDRESS
---------- ------- ----- --------------------------------------------------
gordon         100   213 Jl. jalan pelan-pelan ke Bekasi, Indonesia
mark                     Jl. jalan cepet-cepet ke Jakarta, Indonesia

希望这有帮助!

答案 1 :(得分:2)

这是目标表:

CREATE TABLE my_test
     (
          LastName varchar2(20),
          phone   NUMBER,
          code    varchar2(20),
          address VARCHAR2(100)
     );

填充它的代码:

SET serveroutput ON
DECLARE
l_xml xmltype;
l_val VARCHAR2(1000) := '<begin>
    <entry>
        <lastname>gordon</lastname>
        <numberlist>
            <number>100</number>
            <codelist>
                 <code>213</code>
            </codelist>
        </numberlist>
        <address>
            <addresslist>jl. jalan pelan-pelan ke bekasi, indonesia</addresslist>
        </address>
    </entry>
    <entry>
        <lastname>mark</lastname>
        <address>
            <addresslist>jl. jalan cepet-cepet ke jakarta, indonesia</addresslist>
        </address>
    </entry>
</begin>';
     l_lastname varchar2(50);
     l_phone number;
     l_code number;
     l_address  varchar2(200);
BEGIN
     l_xml        := xmltype(l_val);

     FOR x IN
     (SELECT VALUE(p) col_val
     FROM TABLE(XMLSEQUENCE(EXTRACT(l_xml, '/begin/entry'))) p
     )
     loop

IF x.col_val.existsnode('/entry/lastname/text()') > 0 THEN
         l_lastname := x.col_val.extract('/entry/lastname/text()').getstringval();
END IF;
if x.col_val.existsnode('/entry/numberlist/number/text()') > 0 then
     l_phone := x.col_val.extract('/entry/numberlist/number/text()').getstringval();
end if;
if x.col_val.existsnode('/entry/numberlist/codelist/code/text()') > 0 then
     l_code := x.col_val.extract('/entry/numberlist/codelist/code/text()').getstringval();
end if;
IF x.col_val.existsnode('/entry/address/addresslist/text()') > 0 THEN
         l_address := x.col_val.extract('/entry/address/addresslist/text()').getstringval();
end if;
INSERT INTO my_test
     (
          lastname,
          phone,
          code,
          address
     )
     VALUES
     (
          l_lastname,
          l_phone,
          l_code,
          l_address
     );
     l_lastname := null;
     l_phone := null;
     l_code := null;
     l_address := null;
     end loop;
commit;
end;