2015-05-29 41 views
9

提取數據我有下面一段XML:使用XMLTABLE和XQuery從XML

<per:Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://www.something.com/2014/11/bla/webservice.xsd" 
    xmlns:per="http://www.something.com/2014/11/bla/person"> 
    <per:Initials>E.C.</per:Initials> 
    <per:FirstName>Erik</per:FirstName> 
    <per:LastName>Flipsen</per:LastName> 
    <per:BirthDate>1980-07-01</per:BirthDate> 
    <per:Gender>Male</per:Gender> 
</per:Person> 

從這個XML我想提取的PL/SQL的一些數據。我想使用XMLTABLE,因爲EXTRACT和EXTRACTVALUE函數已被棄用。

我能夠使用此查詢來提取數據:

select pers.Initials, 
     pers.Firstname 
    into lsInitials, 
     lsFirstname 
    from 
    XMLTABLE ('*:Person' passing pxRequest 
    columns Initials   PATH '*:Initials', 
      Firstname   PATH '*:FirstName' 
    ) pers; 

我使用通配符的命名空間,因爲我真的不關心什麼縮略語發送方使用的命名空間,我知道無論如何,哪裏得到我的數據的確切路徑。

有了這個代碼,我有兩件事情讓我困惑:

編輯:

我發現,當我刪除其命名空間的元素,使他們大寫,它的工作原理。因此,列名似乎需要匹配xml元素名稱才能使其工作。我還沒有弄清楚如何使它與命名空間XML協同工作。

  • 該文檔還記錄「對於除FOR ORDINALITY列之外的每個結果列,必須指定列數據類型」,但是,如果沒有它,它似乎工作正常。爲列和指定數據的變量指定它似乎有點多餘。任何想法,如果不指定數據類型可能會讓我陷入麻煩?

可運行的代碼示例:

SET SERVEROUTPUT ON; 
DECLARE 

    pxRequest xmltype := xmltype('<per:Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xsi:schemaLocation="http://www.something.com/2014/11/bla/webservice.xsd" 
            xmlns:per="http://www.something.com/2014/11/bla/person"> 
            <per:Initials>E.C.</per:Initials> 
            <per:FirstName>Erik</per:FirstName> 
            <per:LastName>Flipsen</per:LastName> 
            <per:BirthDate>1980-01-01</per:BirthDate> 
            <per:Gender>Male</per:Gender> 
           </per:Person>'); 
    lsInitials varchar2(100); 
    lsFirstname varchar2(100);         


begin 

    select pers.Initials, 
      pers.Firstname 
     into lsInitials, 
      lsFirstname 
     from 
     XMLTABLE ('*:Person' passing pxRequest 
     columns Initials   PATH '*:Initials', 
       Firstname   PATH '*:FirstName' 
     ) pers; 


    dbms_output.put_line(lsInitials); 
    dbms_output.put_line(lsFirstname); 

end;        

回答

1

作爲每第一個問題,the documentation you linked有這樣一段每天約省略PATH

可選PATH子句指定由XQuery表達式串尋址的所述XQuery的結果的一部分被用作所述列內容。

如果您省略PATH,則假定XQuery表達式列。例如:

(... COLUMNS xyz)

相當於

XMLTable(... COLUMNS xyz PATH 'XYZ')

您可以使用不同的路徑條款分割的XQuery導致成不同的虛擬表列。

原因列xyz被假定爲'XYZ'是因爲Oracle,默認情況下,不區分大小寫(默認爲全部大寫)。如果您已經定義了列"aBcD"那麼PATH值將被假定爲'aBcD'


至於你關於指定數據類型的第二個問題:如果你提取數據始終將是文本數據,你可能能夠逃避不指定數據類型。但是,如果你開始處理日期,時間戳,浮點數等事情,那麼你可能會遇到問題。您需要使用TO_*函數手動轉換它們,或者您可以在列定義中指定它們的數據類型。如果你不這樣做,Oracle可以自由地隱式施放它,但它感覺合適,這可能會產生意想不到的後果。

1

參考文獻:

https://stackoverflow.com/a/9976068/377141

How to parse xml by xmltable when using namespace in xml(Oracle)

應該按預期工作,如果你在你的XMLTABLE的命名空間的元素加載:

select results  
from xmltable( 
    xmlnamespaces(
    default 'http://tempuri.org/',  
    'http://schemas.xmlsoap.org/soap/envelope/' as "soap" 
),  
    'soap:Envelope/soap:Body/addResponse' passing xmltype(v_xml) 
    columns results varchar(100) path './addResult') 

從你的榜樣(您可能還需要提前註冊架構/命名空間,但是這應該是一次):所使用甲骨文的早期版本中工作不工作

select pers.Initials, 
     pers.Firstname 
    into lsInitials, 
     lsFirstname 
    from 
    XMLTABLE (
     xmlnamespaces(
     default 'http://tempuri.org/', 
     'http://www.w3.org/2001/XMLSchema-instance' as "xsi", 
     'http://www.something.com/2014/11/bla/person' as "per" 
    ), 
    passing pxRequest 
    columns Initials   PATH '*:Initials', 
      Firstname   PATH '*:FirstName' 
    ) pers; 

事在11g +中,就我所見,Oracle強烈驗證/輸入XML操作的輸入/輸出,在以前的版本中,您可以運行沒有名稱空間信息的正常正確的XQuery操作。