Phân tích XML trong Oracle PL/SQL
2. XML Parse API
Oracle cung cấp 2 API cơ bản để phân tích (parse) XML:
- DOM (Document Object Model)
- XSLT & XPath
3. Các nguồn dữ liệu XML (XML Data Sources)
Bạn có thể phân tích một tài liệu XML với nguồn dữ liệu từ:
- Nguồn dữ liệu XML là một file.
- Nguồn dữ liệu là văn bản (varchar2,..)
- Nguồn dữ liệu là CLOB
4. Phân tích XML từ nguồn TEXT hoặc CLOB
Ví dụ phân tích một tài liệu XML đơn giản (Nguồn văn bản):
Parse_Xml_Example
Create Or Replace Procedure Parse_Xml_Example As
p Dbms_Xmlparser.Parser;
v_Doc Dbms_Xmldom.Domdocument;
v_Root_Element Dbms_Xmldom.Domelement;
v_Child_Nodes Dbms_Xmldom.Domnodelist;
v_Child_Node Dbms_Xmldom.Domnode;
v_Text_Node Dbms_Xmldom.Domnode;
v_Emp_Nodes Dbms_Xmldom.Domnodelist;
v_Emp_Node Dbms_Xmldom.Domnode;
---
v_Xml_Data Varchar2(4000);
v_Deptno Varchar2(30);
v_Dname Varchar2(100);
v_Location Varchar2(255);
v_Empno Varchar2(30);
v_Ename Varchar2(100);
v_Job Varchar2(100);
v_Hiredate Date;
v_Mrg Number;
v_Sal Number;
--
v_Attr_Nodes Dbms_Xmldom.Domnamednodemap;
v_Attr_Node Dbms_Xmldom.Domnode;
v_Attribute_Name Varchar2(50);
v_Node_Name Varchar2(50);
v_Node_Value Varchar2(100);
Begin
-- Text không chứa <?xml version="1.0"?>
v_Xml_Data := '<department deptno="10" dname="ACCOUNTING" location="NEW YORK">
<employee empno="7782" ename="CLARK">
<job>MANAGER</job>
<mrg>7839</mrg>
<hiredate>6/9/1981</hiredate>
<sal>2450.00</sal>
</employee>
<employee empno="7839" ename="KING">
<job>PRESIDENT</job>
<mrg></mrg>
<hiredate>11/17/1981</hiredate>
<sal>5000.00</sal>
</employee>
<employee empno="7934" ename="MILLER">
<job>CLERK</job>
<mrg>7782</mrg>
<hiredate>1/23/1982</hiredate>
<sal>1300.00</sal>
</employee>
</department>';
-- Tạo một bộ phân tích XML
p := Dbms_Xmlparser.Newparser;
Dbms_Xmlparser.Setvalidationmode(p
,False);
-- Parse XML into DOM object
Dbms_Xmlparser.Parsebuffer(p
,v_Xml_Data);
-- Lấy ra đối tượng Dbms_xmldom.Domdocument
-- (Phần tử mô tả toàn bộ tài liệu)
v_Doc := Dbms_Xmlparser.Getdocument(p);
-- Phần tử gốc của tài liệu (<department>)
v_Root_Element := Dbms_Xmldom.Getdocumentelement(v_Doc);
-- Lấy giá trị của các thuộc tính
v_Deptno := Dbms_Xmldom.Getattribute(v_Root_Element
,'deptno');
v_Dname := Dbms_Xmldom.Getattribute(v_Root_Element
,'dname');
v_Location := Dbms_Xmldom.Getattribute(v_Root_Element
,'location');
---------
Dbms_Output.Put_Line('v_Deptno=' || v_Deptno);
Dbms_Output.Put_Line('v_Dname=' || v_Dname);
Dbms_Output.Put_Line('v_Location=' || v_Location);
--------
-- Danh sách các Node "employee" của v_Root_Element (Dbms_xmldom.Domnodelist)
v_Emp_Nodes := Dbms_Xmldom.Getelementsbytagname(v_Root_Element
,'employee');
For j In 0 .. Dbms_Xmldom.Getlength(v_Emp_Nodes) Loop
v_Emp_Node := Dbms_Xmldom.Item(v_Emp_Nodes
,j);
-- Attribute List (Dbms_xmldom.Domnamednodemap)
v_Attr_Nodes := Dbms_Xmldom.Getattributes(v_Emp_Node);
--
If (Dbms_Xmldom.Isnull(v_Attr_Nodes) = False) Then
For i In 0 .. Dbms_Xmldom.Getlength(v_Attr_Nodes) - 1 Loop
v_Attr_Node := Dbms_Xmldom.Item(v_Attr_Nodes
,i);
v_Node_Name := Dbms_Xmldom.Getnodename(v_Attr_Node);
--
If v_Node_Name = 'empno' Then
v_Empno := Dbms_Xmldom.Getnodevalue(v_Attr_Node);
Elsif v_Node_Name = 'ename' Then
v_Ename := Dbms_Xmldom.Getnodevalue(v_Attr_Node);
End If;
End Loop;
Dbms_Output.Put_Line('v_Empno=' || v_Empno);
Dbms_Output.Put_Line('v_Ename=' || v_Ename);
End If;
----
-- Child nodes of employee node.
--
v_Child_Nodes := Dbms_Xmldom.Getchildnodes(v_Emp_Node);
--
For i In 0 .. Dbms_Xmldom.Getlength(v_Child_Nodes) - 1 Loop
-- <job>,<mrg>,<hiredate>,<sal>
v_Child_Node := Dbms_Xmldom.Item(v_Child_Nodes
,i);
v_Node_Name := Dbms_Xmldom.Getnodename(v_Child_Node);
v_Text_Node := Dbms_Xmldom.Getfirstchild(v_Child_Node);
v_Node_Value := Dbms_Xmldom.Getnodevalue(v_Text_Node);
--
If v_Node_Name = 'job' Then
v_Job := v_Node_Value;
Elsif v_Node_Name = 'mrg' Then
v_Mrg := To_Number(v_Node_Value);
Elsif v_Node_Name = 'hiredate' Then
v_Hiredate := To_Date(v_Node_Value
,'MM/dd/yyyy');
Elsif v_Node_Name = 'sal' Then
v_Sal := To_Number(v_Node_Value);
End If;
End Loop;
--
Dbms_Output.Put_Line('v_Job=' || v_Job);
Dbms_Output.Put_Line('v_Mrg=' || v_Mrg);
Dbms_Output.Put_Line('v_Hiredate=' || v_Hiredate);
Dbms_Output.Put_Line('v_Sal=' || v_Sal);
End Loop;
End;
Chạy thủ tục:
begin
-- Call the procedure
parse_xml_example;
end;
Bạn cũng có thể phân tích XML từ nguồn CLOB.
Declare
p Dbms_Xmlparser.Parser;
v_Xml_Clob Clob;
v_Doc Dbms_Xmldom.Domdocument;
v_Root_Element Dbms_Xmldom.Domelement;
v_Child_Nodes Dbms_Xmldom.Domnodelist;
v_Greeting_Node Dbms_Xmldom.Domnode;
v_Text_Node Dbms_Xmldom.Domnode;
v_Text Varchar2(100);
Begin
-- Một dữ liệu CLOB (Có thể từ cột CLOB của bảng).
v_Xml_Clob := '<data><greeting>Hello</greeting></data>';
-- Tạo một bộ phân tích XML
p := Dbms_Xmlparser.Newparser;
-- Phân tích dữ liệu XML thành các đối tượng DOM.
Dbms_Xmlparser.Parseclob(p
,v_Xml_Clob);
-- Lấy ra đối tượng Dbms_xmldom.Domdocument
-- (Phần tử mô tả toàn bộ tài liệu)
v_Doc := Dbms_Xmlparser.Getdocument(p);
-- Phần tử gốc của tài liệu (<data>)
v_Root_Element := Dbms_Xmldom.Getdocumentelement(v_Doc);
-- Danh sách các node con 'greeting'.
v_Child_Nodes := Dbms_Xmldom.Getchildrenbytagname(v_Root_Element
,'greeting');
-- Phần từ đầu tiên trong danh sách.
v_Greeting_Node := Dbms_Xmldom.Item(v_Child_Nodes
,0);
v_Text_Node := Dbms_Xmldom.Getfirstchild(v_Greeting_Node);
-- Hello
v_Text := Dbms_Xmldom.Getnodevalue(v_Text_Node);
--
Dbms_Output.Put_Line('Greeting:' || v_Text);
End;
5. Phân tích file XML
Trước hết bạn cần tạo ra một thư mục ảo, và gán quyền truy cập vào file trên thư mục đó.
-- Tạo ra một thư mục ảo (Thư mục DBA)
Create Directory MY_XML_DIR as 'C:/TEMP';
-- Gán quyền đọc và ghi trên thư mục này cho user scott.
Grant Read,Write on Directory MY_XML_DIR to scott;
Ví dụ dưới đây phân tích một file xml:
C:/TEMP/company.xml
<company id="111" companyName="Microsoft">
<websites>
<website>http://microsoft.com</website>
<website>http://msn.com</website>
<website>http://hotmail.com</website>
</websites>
<address>
<street>1 Microsoft Way</street>
<city>Redmond</city>
</address>
</company>
Parse_Xml_File_Example
Create Or Replace Procedure Parse_Xml_File_Example As
v_Bfile Bfile;
v_Xml_Clob Clob;
---
p Dbms_Xmlparser.Parser;
v_Doc Dbms_Xmldom.Domdocument;
v_Root_Element Dbms_Xmldom.Domelement;
v_Child_Nodes Dbms_Xmldom.Domnodelist;
v_Child_Node Dbms_Xmldom.Domnode;
v_Text_Node Dbms_Xmldom.Domnode;
v_Text Varchar2(100);
----
v_Dest_Offset Integer := 1;
v_Src_Offset Integer := 1;
v_Lang_Context Number := Dbms_Lob.Default_Lang_Ctx;
v_Warning Integer;
--
v_Value Varchar2(255);
Begin
-- Đối tượng đại diện cho file XML.
v_Bfile := Bfilename('MY_XML_DIR'
,'company.xml');
-- Tạo dữ liệu CLOB rỗng
Dbms_Lob.Createtemporary(v_Xml_Clob
,Cache => False);
-- Mở file XML
Dbms_Lob.Open(v_Bfile
,Dbms_Lob.Lob_Readonly);
-- Tải dữ liệu trong file vào v_Clob.
Dbms_Lob.Loadclobfromfile(v_Xml_Clob -- Dest_Lob IN OUT
,v_Bfile -- Src_Lob In
,Dbms_Lob.Getlength(v_Bfile) -- Amount In
,v_Dest_Offset -- Dest_Offset IN OUT
,v_Src_Offset -- Src_Offset In Out
,Dbms_Lob.Default_Csid -- Bfile_Csid In
,v_Lang_Context -- Lang_Context In Out
,v_Warning -- Warning OUT
);
-- Sau khi đọc xong, đóng lại.
Dbms_Lob.Close(v_Bfile);
--
-- Tạo một bộ phân tích XML
p := Dbms_Xmlparser.Newparser;
--
-- Phân tích dữ liệu XML thành các đối tượng DOM.
Dbms_Xmlparser.Parseclob(p
,v_Xml_Clob);
-- Lấy ra đối tượng Dbms_xmldom.Domdocument
-- (Phần tử mô tả toàn bộ tài liệu)
v_Doc := Dbms_Xmlparser.Getdocument(p);
-- Phần tử gốc của tài liệu (<company>)
v_Root_Element := Dbms_Xmldom.Getdocumentelement(v_Doc);
--
v_Value := Dbms_Xmldom.Getattribute(v_Root_Element
,'id');
Dbms_Output.Put_Line('id=' || v_Value);
v_Value := Dbms_Xmldom.Getattribute(v_Root_Element
,'companyName');
Dbms_Output.Put_Line('companyName=' || v_Value);
--- return Dbms_Xmldom.Domnodelist
v_Child_Nodes := Dbms_Xmldom.Getchildrenbytagname(v_Root_Element
,'*');
For i In 0 .. Dbms_Xmldom.Getlength(v_Child_Nodes) - 1 Loop
v_Child_Node := Dbms_Xmldom.Item(v_Child_Nodes
,i);
--
If Dbms_Xmldom.Getnodename(v_Child_Node) = 'websites' Then
Dbms_Output.Put_Line('Found websites');
-- ...
Elsif Dbms_Xmldom.Getnodename(v_Child_Node) = 'address' Then
Dbms_Output.Put_Line('Found address');
-- ...
End If;
End Loop;
Exception
When Others Then
Dbms_Output.Put_Line(Sqlerrm);
Dbms_Lob.Freetemporary(v_Xml_Clob);
Dbms_Xmlparser.Freeparser(p);
Dbms_Xmldom.Freedocument(v_Doc);
End;
Chạy thủ tục:
begin
-- Call the procedure
parse_xml_file_example;
end;
6. Phân tích XML sử dụng Dbms_Xslprocessor
Oracle Cung cấp cho bạn package Dbms_Xslprocessor giúp bạn truy cập vào dữ liệu XML nhanh chóng và dễ dàng hơn . Hãy xem ví dụ sau:
Declare
v_Xml_Clob Clob;
---
p Dbms_Xmlparser.Parser;
v_Doc Dbms_Xmldom.Domdocument;
v_Root_Element Dbms_Xmldom.Domelement;
v_Child_Nodes Dbms_Xmldom.Domnodelist;
v_Current_Node Dbms_Xmldom.Domnode;
v_Websites_Nodes Dbms_Xmldom.Domnodelist;
--
v_Id Number;
v_Company_Name Varchar2(255);
v_Street Varchar2(255);
v_City Varchar2(50);
v_Note Varchar2(255);
Begin
v_Xml_Clob := '<companies xmlns:my-ns="http://somedomain.com/abc">
<company id="111" companyName="Microsoft">
<websites>
<website>http://microsoft.com</website>
<website>http://msn.com</website>
<website>http://hotmail.com</website>
</websites>
<address>
<street>1 Microsoft Way</street>
<city>Redmond</city>
</address>
<my-ns:note>Microsoft Note</my-ns:note>
</company>
<company id="100" companyName="Apple">
<websites>
<website>http://applet.com</website>
</websites>
<address>
<street>1 Infinite Loop</street>
<city>Cupertino</city>
</address>
<my-ns:note>Apple Note</my-ns:note>
</company>
</companies>';
--
-- Tạo một bộ phân tích XML
p := Dbms_Xmlparser.Newparser;
--
-- Phân tích dữ liệu XML thành các đối tượng DOM.
Dbms_Xmlparser.Parseclob(p
,v_Xml_Clob);
-- Lấy ra đối tượng Dbms_xmldom.Domdocument
-- (Phần tử mô tả toàn bộ tài liệu)
v_Doc := Dbms_Xmlparser.Getdocument(p);
-- Phần tử gốc của tài liệu (<companies>)
v_Root_Element := Dbms_Xmldom.Getdocumentelement(v_Doc);
--- return Dbms_Xmldom.Domnodelist
v_Child_Nodes := Dbms_Xmldom.Getchildrenbytagname(v_Root_Element
,'*');
For i In 0 .. Dbms_Xmldom.Getlength(v_Child_Nodes) - 1 Loop
-- <company> Node.
v_Current_Node := Dbms_Xmldom.Item(v_Child_Nodes
,i);
Dbms_Xslprocessor.Valueof(v_Current_Node
,'@id'
,v_Id -- OUT
);
Dbms_Xslprocessor.Valueof(v_Current_Node
,'@companyName'
,v_Company_Name -- OUT
);
Dbms_Xslprocessor.Valueof(v_Current_Node
,'address/street/text()'
,v_Street -- OUT
);
Dbms_Xslprocessor.Valueof(v_Current_Node
,'address/city/text()'
,v_City -- OUT
);
-- Với trường hợp element có namespace
-- Cần phải thêm tham số thứ 4.
Dbms_Xslprocessor.Valueof(v_Current_Node
,'my-ns:note/text()'
,v_Note -- OUT
,'xmlns:my-ns=http://somedomain.com/abc');
Dbms_Output.Put_Line('v_Id=' || v_Id);
Dbms_Output.Put_Line('v_company_Name=' || v_Company_Name);
Dbms_Output.Put_Line(' - v_street=' || v_Street);
Dbms_Output.Put_Line(' - v_city=' || v_City);
Dbms_Output.Put_Line(' - v_Note=' || v_Note);
-- Lựa chọn các Node phù hợp với đường dẫn.
-- return Dbms_Xmldom.Domnodelist
v_Websites_Nodes := Dbms_Xslprocessor.Selectnodes(v_Current_Node
,'websites/website');
For j In 0 .. Dbms_Xmldom.Getlength(v_Websites_Nodes) - 1 Loop
v_Current_Node := Dbms_Xmldom.Item(v_Websites_Nodes
,j);
Dbms_Output.Put_Line(' - website=' ||
Dbms_Xslprocessor.Valueof(v_Current_Node
,'text()'));
End Loop;
End Loop;
Exception
When Others Then
Dbms_Output.Put_Line(Sqlerrm);
Dbms_Lob.Freetemporary(v_Xml_Clob);
Dbms_Xmlparser.Freeparser(p);
Dbms_Xmldom.Freedocument(v_Doc);
End;
Chạy ví dụ:
Nếu phần tử (element) của bạn có sử dụng namespace:<companies xmlns:my-ns="http://somedomain.com/abc"> <company id="111" companyName="Microsoft"> ..... <my-ns:note>Microsoft Note</my-ns:note> </company> .... </companies>
Bạn cần phải thêm tham số chỉ định namespace:Dbms_Xslprocessor.Valueof(v_Current_Node ,'my-ns:note/text()' ,v_Note -- OUT ,'xmlns:my-ns=http://somedomain.com/abc');
Ngược lại bạn sẽ nhận được lỗi:ORA-31011: XML parsing failed ORA-19202: Error occurred in XML processing LPX-00601: Invalid token in: 'my-ns:note/text()'
Các hướng dẫn về cơ sở dữ liệu Oracle
- Cài đặt PL/SQL Developer trên Windows
- Cơ sở dữ liệu Oracle mẫu để học SQL
- Hướng dẫn học SQL cho người mới bắt đầu với Oracle
- Cài đặt cơ sở dữ liệu Oracle 11g trên Windows
- Cài đặt cơ sở dữ liệu Oracle 12c trên Windows
- Cài đặt Oracle Client trên Windows
- Tạo Oracle SCOTT Schema
- Cơ sở dữ liệu mẫu
- Cấu trúc database và tính năng đám mây trong Oracle 12c
- Import và Export cơ sở dữ liệu Oracle
- Các hàm xử lý chuỗi trong Oracle
- Phân tách một chuỗi ngăn cách bởi dấu phẩy và chuyển vào mệnh đề IN của câu lệnh Select trong Oracle
- Truy vấn phân cấp trong Oracle
- Hướng dẫn và ví dụ Oracle Database Link và Synonym
- Hướng dẫn lập trình Oracle PL/SQL
- Phân tích XML trong Oracle PL/SQL
- Kiểm soát chuẩn hệ thống database Oracle (Audit Standard)
- Kiểm soát bắt buộc và kiểm soát quản trị trong Oracle
- Tạo và quản lý Oracle Wallet
Show More