Oracle PLSQL調用第三方SOAP Web Services時,需要使Oracle內置一些XML解析函數,它可以很方便的解析SOAP Web Services返回XML內容,下面介紹常用XML內置函數和使用方法:
- EXTRACT(XMLType_instance,XPath_string,[namespace_string])用法
該函數用於獲得XML某節點或某節點集
1.1 獲得Cities節點內容SELECT Extract(Xmltype('<?xml version="1.0" encoding="utf-8"?> <Root> <Cities> <City><Id>1</Id><CityName>北京市</CityName><ZipCode>100000</ZipCode></City> <City><Id>2</Id><CityName>天津市</CityName><ZipCode>100001</ZipCode></City> <City><Id>3</Id><CityName>石家莊市</CityName><ZipCode>050000</ZipCode></City> <City><Id>4</Id><CityName>唐山市</CityName><ZipCode>063000</ZipCode></City> <City><Id>5</Id> <CityName>秦皇島市</CityName><ZipCode>066000</ZipCode></City> <City><Id>6</Id><CityName>邯鄲市</CityName><ZipCode>056000</ZipCode></City> </Cities> </Root>') ,'/Root/Cities') FROM Dual;
SELECT Extract(Xmltype('<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <MFCRequest> <Cities> <City><Id>1</Id><CityName>北京市</CityName><ZipCode>100000</ZipCode></City> <City><Id>2</Id><CityName>天津市</CityName><ZipCode>100001</ZipCode></City> <City><Id>3</Id><CityName>石家莊市</CityName><ZipCode>050000</ZipCode></City> <City><Id>4</Id><CityName>唐山市</CityName><ZipCode>063000</ZipCode></City> <City><Id>5</Id> <CityName>秦皇島市</CityName><ZipCode>066000</ZipCode></City> <City><Id>6</Id><CityName>邯鄲市</CityName><ZipCode>056000</ZipCode></City> </Cities> </MFCRequest> </soap:Body> </soap:Envelope>'),'/soap:Envelope/soap:Body/MFCRequest','xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"') from dual;
參考官方API:https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions051.htm
- EXTRACTVALUE(XMLType_instance,XPath_string,[namespace_string])用法
該函數用於返回特定XML節點路徑的數據
2.1 獲某元素的值SELECT Extractvalue(Xmltype('<?xml version="1.0" encoding="utf-8"?> <Root> <Cities> <City> <Id>1</Id><CityName>北京市</CityName><ZipCode>100000</ZipCode> </City> </Cities> </Root>') ,'/Root/Cities/City/CityName') FROM Dual;
2.2 獲某帶命名空間XML中某元素的值SELECT Extractvalue(Xmltype('<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body> <MFCRequestResponse> <MFCRequestResult> <IsSuccessed>false</IsSuccessed> <Message>用戶驗證失敗</Message> </MFCRequestResult> </MFCRequestResponse> </soap:Body> </soap:Envelope>') ,'/soap:Envelope/soap:Body/MFCRequestResponse/MFCRequestResult/IsSuccessed' ,'xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"') FROM Dual;
注意:EXTRACTVALUE只能解析單一XML葉子節點的值。不能解析根節點和子節點的內容,或多個相同XML葉子節點的值
參考官方API:https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions052.htm#i1131042 - 錶轉換XML
3.1 DBMS_XMLGEN.GETXML 錶轉換XMLSELECT Dbms_Xmlgen.Getxml('SELECT Msi.Segment1 Item_Num ,Msi.Description Item_Desc ,Msi.Primary_Unit_Of_Measure UOM FROM Mtl_System_Items_b Msi WHERE Msi.Organization_Id = 82 AND Rownum <= 30') FROM Dual;
1.默認根元素爲<ROWSET>和每行的節點元素爲<ROW>
2.列名或列別名爲各個值的元素
參考官方API:https://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_xmlgen.htm#i1012053
3.2 XMLELEMENT、XMLFOREST和XMLAGG結合使用
XMLAGG 函數用於彙總所有XML文檔,並生成一個XML文檔。SELECT XMLELEMENT("ITEMS" ,Xmlagg(Xmlelement("ITEM" ,XMLFOREST(Msi.Segment1 Item_Number ,Msi.Description Item_Desc)))) FROM Mtl_System_Items_b Msi WHERE Msi.Organization_Id = 82 AND Rownum <= 10;
參考官方API:https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions215.htm
3.3 二層或多層級XML結構實例,如BOM清單:SELECT Xmlelement("BOMS" --第一層 ,Xmlagg(Xmlelement("BOM" --第二層 ,Xmlforest(Bbm.Bill_Sequence_Id ,Bbm.Organization_Id ,Bbm.Assembly_Item_Id ,Msi.Segment1 Assembly_Item ,Msi.Description Assembly_Desc) ----Componentes Start--------------------- ,(SELECT Xmlelement("COMPONENTS" ,Xmlagg(Xmlelement("COMPONENT" ,Xmlforest(Bic.Component_Sequence_Id ,Bic.Component_Item_Id ,Msi.Segment1 Component_Item ,Msi.Description Component_Desc)))) AS Components FROM Bom_Inventory_Components Bic ,Mtl_System_Items_b Msi WHERE Bic.Component_Item_Id = Msi.Inventory_Item_Id AND Bic.Effectivity_Date <= SYSDATE AND Nvl(Bic.Disable_Date, SYSDATE) >= Trunc(SYSDATE) AND Bic.Bill_Sequence_Id = Bbm.Bill_Sequence_Id AND Msi.Organization_Id = Bbm.Organization_Id) ----Componentes End--------------------- ))) FROM Bom_Bill_Of_Materials Bbm ,Mtl_System_Items_b Msi WHERE Bbm.Assembly_Item_Id = Msi.Inventory_Item_Id AND Bbm.Organization_Id = Msi.Organization_Id AND Bbm.Bill_Sequence_Id IN (SELECT DISTINCT Bic.Bill_Sequence_Id FROM Bom_Inventory_Components Bic WHERE Bic.Effectivity_Date <= SYSDATE AND Nvl(Bic.Disable_Date, SYSDATE) >= Trunc(SYSDATE) AND Rownum < 2);
<BOMS> <BOM> <BILL_SEQUENCE_ID>1</BILL_SEQUENCE_ID> <ORGANIZATION_ID>83</ORGANIZATION_ID> <ASSEMBLY_ITEM_ID>3</ASSEMBLY_ITEM_ID> <ASSEMBLY_ITEM>1110010001</ASSEMBLY_ITEM> <ASSEMBLY_DESC>子裝配件</ASSEMBLY_DESC> <COMPONENTS> <COMPONENT> <COMPONENT_SEQUENCE_ID>2</COMPONENT_SEQUENCE_ID> <COMPONENT_ITEM_ID>1</COMPONENT_ITEM_ID> <COMPONENT_ITEM>WD01</COMPONENT_ITEM> <COMPONENT_DESC>家用電器</COMPONENT_DESC> </COMPONENT> <COMPONENT> <COMPONENT_SEQUENCE_ID>3</COMPONENT_SEQUENCE_ID> <COMPONENT_ITEM_ID>2</COMPONENT_ITEM_ID> <COMPONENT_ITEM>WD02</COMPONENT_ITEM> <COMPONENT_DESC>家用電扇</COMPONENT_DESC> </COMPONENT> </COMPONENTS> </BOM> </BOMS>
- XMLTABLE([XML_namespace],XQuery_string,XMLTABLE_options)(XML轉換表用法)
4.1 XML轉換表SELECT * FROM Xmltable('/Cities/City' Passing Xmltype('<?xml version="1.0" encoding="utf-8"?> <Cities> <City><Id>1</Id><CityName>北京市</CityName><ZipCode>100000</ZipCode></City> <City><Id>2</Id><CityName>天津市</CityName><ZipCode>100001</ZipCode></City> <City><Id>3</Id><CityName>石家莊市</CityName><ZipCode>050000</ZipCode></City> <City><Id>4</Id><CityName>唐山市</CityName><ZipCode>063000</ZipCode></City> <City><Id>5</Id> <CityName>秦皇島市</CityName><ZipCode>066000</ZipCode></City> <City><Id>6</Id><CityName>邯鄲市</CityName><ZipCode>056000</ZipCode></City> </Cities>') Columns City_Id NUMBER Path '/City/Id' ,City_Name VARCHAR2(240) Path '/City/CityName' ,Zip_Code VARCHAR2(10) Path '/City/ZipCode')
4.2 XML轉錶帶命名空間SELECT * FROM XMLTABLE(XMLNAMESPACES('http://schemas.xmlsoap.org/soap/envelope/' AS "soapenv1", 'http://platform.nucleusconnect.com/wsdl/EUCServices' AS "euc1"), '$B/soapenv1:Envelope/soapenv1:Body/euc1:EUCRevisionNewOrderRequest/body' PASSING (select xmltype('<?xml version="1.0" encoding="utf-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:euc="http://platform.nucleusconnect.com/wsdl/EUCServices"> <soapenv:Body> <euc:EUCRevisionNewOrderRequest> <header> <Department>Business Solution - Business Broadband</Department> <AcceptTNC>Yes</AcceptTNC> <TransactionId>FB000120170119181518436</TransactionId> </header> <body> <SalesOrderId>2017011914381897</SalesOrderId> </body> <body> <SalesOrderId>2017011914381897</SalesOrderId> </body> </euc:EUCRevisionNewOrderRequest> </soapenv:Body> </soapenv:Envelope>') from dual a ) AS B COLUMNS SalesOrderId VARCHAR2(128) PATH '/body/SalesOrderId')
參考官方API:https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions228.htm - EXISTSNODE(XMLType_instance,XPath_string,namespace_string)用法
該函數用於確定特定的XML節點的路徑是否存在,返回0表示節點不存在,返回1表示節點存在。
如下:判斷XML中/Cities/City下Id元素爲2的值是否存在WITH Xmlcities AS (SELECT Xmltype('<?xml version="1.0" encoding="utf-8"?> <Cities> <City><Id>1</Id><CityName>北京市</CityName><ZipCode>100000</ZipCode></City> <City><Id>2</Id><CityName>天津市</CityName><ZipCode>100001</ZipCode></City> <City><Id>3</Id><CityName>石家莊市</CityName><ZipCode>050000</ZipCode></City> <City><Id>4</Id><CityName>唐山市</CityName><ZipCode>063000</ZipCode></City> <City><Id>5</Id> <CityName>秦皇島市</CityName><ZipCode>066000</ZipCode></City> <City><Id>6</Id><CityName>邯鄲市</CityName><ZipCode>056000</ZipCode></City> </Cities>') AS Xml_Object FROM Dual) SELECT * FROM Xmlcities T1 WHERE Existsnode(Xml_Object, '/Cities/City[Id="2"]') = 1
- 無法表格化的XML解析實例腳本
DECLARE --創建XML解析器實例XMLPARSER.parser Xmlpar Xmlparser.Parser := Xmlparser.Newparser; --定義DOM文檔對象 Xmldoc Xmldom.Domdocument; --定義解析XML所需要的其他對象 Lo_City_Nodelist Xmldom.Domnodelist; --City節點集 Lo_City_Node Xmldom.Domnode; --City節點 Ln_City_Count NUMBER; Chilnodes Xmldom.Domnodelist; --City節點下元素 Ln_City_Id NUMBER; Lv_City_Name VARCHAR2(240); Lv_Zip_Code VARCHAR2(10); Xmlclobdata CLOB := '<?xml version="1.0" encoding="utf-8"?> <Cities> <City><Id>1</Id><CityName>北京市</CityName><ZipCode>100000</ZipCode></City> <City><Id>2</Id><CityName>天津市</CityName><ZipCode>100001</ZipCode></City> <City><Id>3</Id><CityName>石家莊市</CityName><ZipCode>050000</ZipCode></City> <City><Id>4</Id><CityName>唐山市</CityName><ZipCode>063000</ZipCode></City> <City><Id>5</Id> <CityName>秦皇島市</CityName><ZipCode>066000</ZipCode></City> <City><Id>6</Id><CityName>邯鄲市</CityName><ZipCode>056000</ZipCode></City> </Cities>'; BEGIN --創建XML解析對象 Xmlpar := Xmlparser.Newparser; BEGIN --解析文檔並創建一個新的DOM文檔。 Xmlparser.Parseclob(Xmlpar, Xmlclobdata); EXCEPTION WHEN OTHERS THEN Dbms_Output.Put_Line('Xml文件格式錯誤或者不完整'); RETURN; END; --獲得XML文檔 Xmldoc := Xmlparser.Getdocument(Xmlpar); --釋放解析器實例 Xmlparser.Freeparser(Xmlpar); --獲取所有City節點 Lo_City_Nodelist := Xmldom.Getelementsbytagname(Xmldoc, 'City'); --獲得City節點個數 Ln_City_Count := Xmldom.Getlength(Lo_City_Nodelist); Dbms_Output.Put_Line('Ln_City_Count:' || Ln_City_Count); --遍歷City節點 FOR i IN 0 .. Ln_City_Count - 1 LOOP --獲得City節點 Lo_City_Node := Xmldom.Item(Lo_City_Nodelist, i); Chilnodes := Xmldom.Getchildnodes(Lo_City_Node); --獲取City節點元素 Ln_City_Id := Xmldom.Getnodevalue(Xmldom.Getfirstchild(Xmldom.Item(Chilnodes ,0))); Lv_City_Name := Xmldom.Getnodevalue(Xmldom.Getfirstchild(Xmldom.Item(Chilnodes ,1))); Lv_Zip_Code := Xmldom.Getnodevalue(Xmldom.Getfirstchild(Xmldom.Item(Chilnodes ,2))); Dbms_Output.Put('Ln_City_Id:' || Ln_City_Id); Dbms_Output.Put(',Lv_City_Name:' || Lv_City_Name); Dbms_Output.Put(',Lv_Zip_Code:' || Lv_Zip_Code); Dbms_Output.Put_Line(''); END LOOP; --釋放文檔對象 Xmldom.Freedocument(Xmldoc); --異常與錯誤處理 EXCEPTION WHEN OTHERS THEN Dbms_Output.Put_Line(SQLERRM); END;