2015-05-29 14 views
9

Tôi có mảnh sau của XML:Sử dụng XMLTABLE và XQuery để trích xuất dữ liệu từ 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> 

Từ xml này tôi muốn trích xuất một số dữ liệu trong PL/SQL. Tôi muốn sử dụng XMLTABLE, vì các hàm EXTRACT và EXTRACTVALUE không được chấp nhận.

tôi có thể trích xuất các dữ liệu sử dụng truy vấn này:

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

Tôi đang sử dụng ký tự đại diện cho các không gian tên kể từ khi tôi không thực sự quan tâm những gì chữ viết tắt bên gửi được sử dụng cho các không gian tên, tôi biết con đường chính xác nơi để lấy dữ liệu của tôi.

Với mã này, tôi có hai điều mà câu đố tôi:

Edit:

tôi phát hiện ra rằng khi tôi loại bỏ các không gian tên cho các yếu tố, và làm cho họ chữ hoa, nó hoạt động. Vì vậy, có vẻ như các tên cột cần phải khớp với các tên phần tử xml để làm cho nó hoạt động. Tôi chưa tìm ra cách làm cho nó hoạt động với XML không gian tên.

  • Tài liệu cũng ghi chú "Đối với mỗi cột kết quả ngoại trừ cột FOR ORDINALITY, bạn phải chỉ định loại dữ liệu cột", tuy nhiên, có vẻ như hoạt động tốt mà không có nó. Nó cũng có vẻ hơi dư thừa để chỉ định nó cho các cột và cho các biến tôi đang tìm nạp dữ liệu vào. Bất kỳ ý tưởng nếu không chỉ định các loại dữ liệu có thể làm cho tôi gặp rắc rối?

mẫu mã Runnable:

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;        

Trả lời

1

Theo câu hỏi đầu tiên của bạn, the documentation you linked có này cho đến ngày về bỏ PATH:

Các PATH khoản tùy chọn xác định rằng một phần của kết quả XQuery được giải quyết bằng chuỗi biểu thức XQuery là để được sử dụng làm nội dung cột.

Nếu bạn bỏ qua PATH, thì cột biểu thức XQuery được giả định. Ví dụ:

(... COLUMNS xyz)

tương đương với

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

Bạn có thể sử dụng khoản PATH khác nhau để phân chia các XQuery kết quả vào cột ảo-bảng khác nhau.

Lý do cột xyz được giả định là 'XYZ' là bởi vì Oracle, theo mặc định, là trường hợp nhạy cảm (mặc định là tất cả-mũ). Nếu bạn đã định nghĩa cột của bạn như "aBcD" thì giá trị PATH sẽ được giả định là 'aBcD'


Đối với câu hỏi thứ hai của bạn về cách xác định kiểu dữ liệu: nếu dữ liệu bạn đang giải nén luôn sẽ là dữ liệu văn bản, bạn có thể thoát khỏi việc không chỉ định loại dữ liệu.

Tuy nhiên, nếu bạn bắt đầu xử lý những thứ như ngày, dấu thời gian, số dấu chấm động, v.v. thì bạn có thể gặp sự cố. Bạn sẽ cần phải chuyển đổi chúng theo cách thủ công bằng cách sử dụng các hàm TO_* hoặc bạn có thể chỉ định loại dữ liệu của chúng trong định nghĩa cột. Nếu bạn không làm như vậy, Oracle hoàn toàn tự do sử dụng nó, tuy nhiên nó cảm thấy phù hợp, có thể có những hậu quả bất ngờ.

1

Tài liệu tham khảo:

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

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

Nó sẽ làm việc như mong đợi nếu bạn nạp trong các yếu tố không gian tên trong XMLTABLE của bạn:

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') 

Từ ví dụ của bạn (bạn cũng có thể cần phải đăng ký giản đồ của bạn/namespace trước thời hạn, nhưng đó phải là một lần):

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; 

Những điều đó đã từng làm việc trong các phiên bản trước của Oracle không làm việc trong 11g + đối với XML, như những gì tôi thấy, Oracle mạnh mẽ xác minh/loại đầu vào/đầu ra của các hoạt động XML trong các phiên bản trước, bạn có thể chạy các hoạt động XQuery bình thường thích hợp mà không có thông tin không gian tên.

Các vấn đề liên quan