最近在研究Oracle PLSQL中對于XML的系列操作。結合工作中使用的知識和參考資料整理出以下相關(guān)內容:
一 如何生成XML文件:
1、使用dbms_xmlquery和utl_file內置包(scott用戶(hù)執行)
- CREATE OR REPLACE DIRECTORY xml_dir AS 'd:\app\xml';
-
- DROP SEQUENCE seq_filename;
- CREATE SEQUENCE seq_filename
- MINVALUE 10000
- MAXVALUE 99999
- INCREMENT BY 1
- START WITH 10000
- NOCYCLE;
- DECLARE
- v_filename Varchar2(50) := 'Empmsg'||to_char(seq_filename.nextval)||'.xml';
- xml_str clob;
- xml_file utl_file.file_type;
- offset number;
- buffer varchar2(32767);
- buffer_size number;
- BEGIN
- offset := 1;
- buffer_size := 3000;
- xml_file := utl_file.fopen('XML_DIR', v_filename, 'w');
- xml_str := dbms_xmlquery.getxml('select empno,
- ename,
- job,
- mgr,
- hiredate,
- sal,
- comm,
- deptno
- from emp');
-
- while (offset < dbms_lob.getlength(xml_str)) loop
- buffer := dbms_lob.substr(xml_str, buffer_size, offset);
- utl_file.put(xml_file, buffer);
- utl_file.fflush(xml_file);
- offset := offset + buffer_size;
- end loop;
-
- utl_file.fclose(xml_file);
- END;
2、使用XMLELEMENT系列內置函數返回xml(sys用戶(hù)執行)
- DECLARE
- v_filename Varchar2(50) := 'Empmsg'||to_char(scott.seq_filename.nextval)||'.xml';
- xml_str clob;
- xml_file utl_file.file_type;
- offset number;
- buffer varchar2(32767);
- buffer_size number;
- BEGIN
- offset := 1;
- buffer_size := 3000;
- xml_file := utl_file.fopen('XML_DIR', v_filename, 'w');
- SELECT XMLElement("DEPARTMENT"
- , XMLAttributes( department_id as "ID"
- , department_name as "NAME"
- )
- , XMLElement("EMPLOYEES"
- , (SELECT XMLAgg( XMLElement("EMPLOYEE"
- , XMLForest(employee_id as "ID"
- ,first_name||' '||last_name as "NAME"
- )
- )
- )
- FROM hr.employees emp
- WHERE emp.department_id = dept.department_id
- )
- )
- ).getclobval() INTO xml_str
- FROM hr.departments dept
- WHERE department_id = 20;
-
- while (offset < dbms_lob.getlength(xml_str)) loop
- buffer := dbms_lob.substr(xml_str, buffer_size, offset);
- utl_file.put(xml_file, buffer);
- utl_file.fflush(xml_file);
- offset := offset + buffer_size;
- end loop;
-
- utl_file.fclose(xml_file);
- END;
--XMLElement: 將一個(gè)關(guān)系值轉換為XML元素的函數,格式為<elementName>值</elementName>
--XMLAttributes: 用于在SQL查詢(xún)返回的 XML 元素中設置屬性的函數
--XMLForest: 該函數返回一個(gè)或多個(gè)子元素的集合,該函數使用列名做為XML元素的名稱(chēng)并用SQL值表達式做為XML元素的內容,但使用時(shí)不能指定元素的屬性
--XMLAgg: 在GROUP BY查詢(xún)中對XML數據進(jìn)行分組或匯總的函數
PS: 使用SPOOL方式導出文件:
- SET TRIMSPOOL ON
- SET TERMOUT ON
- SET FEEDBACK OFF
- SET VERIFY OFF
- SET ECHO OFF
- SET PAGESIZE 999
- SET HEAD OFF
- SET HEADING OFF
- SET LONG 5000
- spool c:\a.xml
- SELECT XMLElement("DEPARTMENT"
- , XMLAttributes( department_id as "ID"
- , department_name as "NAME"
- )
- , XMLElement("EMPLOYEES"
- , (SELECT XMLAgg( XMLElement("EMPLOYEE"
- , XMLForest(employee_id as "ID"
- ,first_name||' '||last_name as "NAME"
- )
- )
- )
- FROM employees emp
- WHERE emp.department_id = dept.department_id
- )
- )
- ) a
- FROM departments dept
- WHERE department_id = 10;
- spool off
二 如何存儲XML文件內容:
我們知道oracle 中xmltype數據類(lèi)型用來(lái)存儲XML內容。下面例子中介紹如何將系統中XML文件內容加載至
含有XMLTYPE類(lèi)型的表中。
- CREATE TABLE xml_table OF XMLTYPE;
-
- INSERT INTO xml_table
- VALUES(XMLTYPE(bfilename('XML_DIR','PurchaseOrder.xml'),nls_charset_id('AL32UTF8')));
-
- SELECT x.sys_nc_rowinfo$.getstringval() FROM xml_table x;
-
- CREATE TABLE table_with_xml_column(filename VARCHAR2(64), xml_document XMLTYPE);
-
- INSERT INTO table_with_xml_column
- VALUES ('PurchaseOrder.xml',XMLType(bfilename('XML_DIR', 'PurchaseOrder.xml'),nls_charset_id('AL32UTF8')));
-
- SELECT x.xml_document.getCLOBVal() FROM table_with_xml_column x;
PurchaseOrder.xml內容:
- <PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:noNamespaceSchemaLocation=
- "http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd">
- <Reference>SBELL-2002100912333601PDT</Reference>
- <Actions>
- <Action>
- <User>SVOLLMAN</User>
- </Action>
- </Actions>
- <Reject/>
- <Requestor>Sarah J. Bell</Requestor>
- <User>SBELL</User>
- <CostCenter>S30</CostCenter>
- <ShippingInstructions>
- <name>Sarah J. Bell</name>
- <address>400 Oracle Parkway
- Redwood Shores
- CA
- 94065
- USA</address>
- <telephone>650 506 7400</telephone>
- </ShippingInstructions>
- <SpecialInstructions>Air Mail</SpecialInstructions>
- <LineItems>
- <LineItem ItemNumber="1">
- <Description>A Night to Remember</Description>
- <Part Id="715515009058" UnitPrice="39.95" Quantity="2"/>
- </LineItem>
- <LineItem ItemNumber="2">
- <Description>The Unbearable Lightness Of Being</Description>
- <Part Id="37429140222" UnitPrice="29.95" Quantity="2"/>
- </LineItem>
- <LineItem ItemNumber="3">
- <Description>Sisters</Description>
- <Part Id="715515011020" UnitPrice="29.95" Quantity="4"/>
- </LineItem>
- </LineItems>
- </PurchaseOrder>
三 如何解析XML內容:
1、XPath結構介紹:
/ 表示樹(shù)根。例如:/PO 指向樹(shù)根的子節點(diǎn)<PO>; 通常也作為路徑分隔符使用,例如:/A/B
// 表示當前節點(diǎn)下所有子節點(diǎn);例如:/A//B 匹配A節點(diǎn)下所有B節點(diǎn)
* 作為通配符使用,匹配所有子節點(diǎn); 如:/A/*/C 匹配A節點(diǎn)下所有子節點(diǎn)C
[ ] 表示預期表達式;XPath支持豐富的操作符如OR、AND、NOT等;例如:/PO[PONO=20 AND PNAME="PO_2"]/SHIPADDR 匹配所有訂單號為20并且訂單名為PO_2的送貨地址
@ 用來(lái)提取節點(diǎn)屬性
FunctionsXPath支持一些內置函數如:substring(), round() 和 not().
2、使用XMLTYPE方法查詢(xún)XML:
SELECT x.OBJECT_VALUE.getCLOBVal() FROM xml_table x;
SELECT x.OBJECT_VALUE.getSTRINGVal() FROM xml_table x;
3、使用函數解析XML:
--existsNode 判斷XPath中節點(diǎn)是否存在,存在返回值1 不存在返回0;
- SELECT existsNode(OBJECT_VALUE, '/PurchaseOrder/Reference')
- FROM purchaseorder;
--extractValue 提取XPath節點(diǎn)值- SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/Reference')
- FROM purchaseorder
- WHERE existsNode(OBJECT_VALUE, '/PurchaseOrder/Reference') = 1;
--extract 提取XPath節點(diǎn)- SELECT extract(OBJECT_VALUE, '/PurchaseOrder/Reference') "REFERENCE"
- FROM purchaseorder;
4、使用SQL解析XML:
- SELECT extractValue(OBJECT_VALUE, '/PurchaseOrder/Reference') REFERENCE,
- extractValue(OBJECT_VALUE, '/PurchaseOrder/*//User') USERID,
- CASE
- WHEN existsNode(OBJECT_VALUE, '/PurchaseOrder/Reject') = 1
- THEN 'Rejected'
- ELSE 'Accepted'
- END "STATUS",
- extractValue(OBJECT_VALUE, '//CostCenter') CostCenter
- FROM purchaseorder
- WHERE existsNode(OBJECT_VALUE,'//Reject') = 1;
四 XMLTABLE用法:
XMLTable maps the result of an XQuery evaluation into relational rows and columns. You can query the result returned by the function as a virtual relational table using SQL.
說(shuō)白了就是解析XML內容返回虛擬關(guān)系型結構數據。 下面說(shuō)個(gè)簡(jiǎn)單例子:
- CREATE TABLE warehouses(
- warehouse_id NUMBER(3),
- warehouse_spec SYS.XMLTYPE,
- warehouse_name VARCHAR2(35),
- location_id NUMBER(4)
- );
- INSERT into warehouses (warehouse_id, warehouse_spec,warehouse_name) VALUES (100, sys.XMLType.createXML(
-
- '<Warehouse whNo="100">
- <opt1>
- <Building>Owned</Building>
- <WaterAccess>WaterAccess</WaterAccess>
- <RailAccess>RailAccess</RailAccess>
- <field>f1</field>
- <field>f2</field>
- <field>f3</field>
- </opt1>
- <opt2>
- <name>Dylan</name>
- </opt2>
- </Warehouse>'),'Warehouse-X');
- SELECT warehouse_name warehouse,
- warehouse2."whNo"
- FROM warehouses,
- XMLTABLE('/Warehouse'
- PASSING warehouses.warehouse_spec
- COLUMNS
- "whNo" varchar2(100) PATH '@whNo')
- warehouse2;
- SELECT warehouse_name warehouse,
- warehouse2."Water", warehouse2."Rail", warehouse2.field
- FROM warehouses,
- XMLTABLE('*//opt1'
- PASSING warehouses.warehouse_spec
- COLUMNS
- "Water" varchar2(100) PATH '//WaterAccess',
- "Rail" varchar2(100) PATH '//RailAccess',
- field XMLTYPE PATH '/')
- warehouse2;
to be continue...
----------------------------------
By Dylan.
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請
點(diǎn)擊舉報。