PLSQL 解析XML示例1
1:xml数据格式如下:
<ns1:IncreaseCreditAfterRemittance xmlns:ns1="http://tempuri.org/"> <ns1:parameters> <ns1:RemittanceParameterItem> <ns1:LeagueCompanyId>2001116</ns1:LeagueCompanyId> <ns1:CompanyId>1000</ns1:CompanyId> <ns1:RemittanceValue>65000.0</ns1:RemittanceValue> <ns1:RemittanceToken>9591503</ns1:RemittanceToken> <ns1:RemittanceDateTime>2018-09-26T14:51:22.0Z</ns1:RemittanceDateTime> <ns1:Remark>640001391210002018</ns1:Remark> </ns1:RemittanceParameterItem> </ns1:parameters> </ns1:IncreaseCreditAfterRemittance>
2:定义type increasecreditafterremittance来暂存解析出来的各字段,这里以xml根节点名称来命名类型,如下:typ和tyb
CREATE OR REPLACE TYPE increasecreditafterremittance AS OBJECT ( leaguecompanyid VARCHAR2(4000), companyid VARCHAR2(4000), remittancevalue INTEGER, remittancetoken VARCHAR2(32767), remittancedatetime VARCHAR2(32767), remark VARCHAR2(32767), CONSTRUCTOR FUNCTION increasecreditafterremittance RETURN SELF AS RESULT ); CREATE OR REPLACE TYPE BODY increasecreditafterremittance AS CONSTRUCTOR FUNCTION increasecreditafterremittance RETURN SELF AS RESULT IS BEGIN RETURN; END; END;
3:定义对应的解析包程序,把一些公共的解析程序放入公用包中,提高代码复用,如下:分别定义soapdeccommon.pkg和soapdeccommon.pkb
CREATE OR REPLACE PACKAGE soapdeccommon IS ------------------------------------ --author:xy --date:20181009 --description:用于解析XML中具体类型字段 ------------------------------------ FUNCTION decode_string(p_node IN dbms_xmldom.domnode) RETURN VARCHAR2; FUNCTION decode_int(p_node IN dbms_xmldom.domnode) RETURN INTEGER; FUNCTION decode_integer(p_node IN dbms_xmldom.domnode) RETURN INTEGER; FUNCTION decode_calendar(p_node IN dbms_xmldom.domnode) RETURN TIMESTAMP WITH TIME ZONE; FUNCTION decd_incr_creditafremittance(p_node IN dbms_xmldom.domnode) RETURN increasecreditafterremittance; END soapdeccommon; CREATE OR REPLACE PACKAGE BODY soapdeccommon IS ------------------------------------ --author:xy --date:20181009 --description:用于解析XML中具体类型字段 ------------------------------------ FUNCTION decode_string(p_node IN dbms_xmldom.domnode) RETURN VARCHAR2 IS l_children dbms_xmldom.domnodelist; l_length INTEGER; l_i INTEGER; l_child dbms_xmldom.domnode; l_char_data dbms_xmldom.domcharacterdata; BEGIN l_children := dbms_xmldom.getchildnodes(p_node); l_length := dbms_xmldom.getlength(l_children); l_i := 0; WHILE l_i < l_length LOOP l_child := dbms_xmldom.item(l_children, l_i); IF dbms_xmldom.getnodetype(l_child) = dbms_xmldom.text_node THEN l_char_data := dbms_xmldom.makecharacterdata(l_child); RETURN dbms_xmldom.getdata(l_char_data); END IF; l_i := l_i + 1; END LOOP; RETURN ''; END; FUNCTION decode_int(p_node IN dbms_xmldom.domnode) RETURN INTEGER IS BEGIN RETURN to_number(decode_string(p_node)); END; FUNCTION decode_integer(p_node IN dbms_xmldom.domnode) RETURN INTEGER IS BEGIN RETURN to_number(decode_string(p_node)); END; FUNCTION decode_calendar(p_node IN dbms_xmldom.domnode) RETURN TIMESTAMP WITH TIME ZONE IS l_decode_result VARCHAR2(32767); l_calendar TIMESTAMP WITH TIME ZONE; BEGIN l_decode_result := decode_string(p_node); l_calendar := NULL; BEGIN l_calendar := to_timestamp_tz(l_decode_result, 'YYYY-MM-DD"T"HH24:MI:SSTZH:TZM'); EXCEPTION WHEN OTHERS THEN BEGIN BEGIN l_calendar := to_timestamp_tz(l_decode_result, 'YYYY-MM-DD"T"HH24:MI:SS'); EXCEPTION WHEN OTHERS THEN BEGIN l_calendar := to_timestamp_tz(l_decode_result, 'YYYY-MM-DD"T"HH24:MI:SS"Z"'); END; END; END; END; RETURN l_calendar; END; FUNCTION decd_incr_creditafremittance(p_node IN dbms_xmldom.domnode) RETURN increasecreditafterremittance IS l_obj increasecreditafterremittance; l_children dbms_xmldom.domnodelist; l_length INTEGER; l_i INTEGER; l_child dbms_xmldom.domnode; l_name VARCHAR2(32767); l_decode_result VARCHAR2(32767); BEGIN l_obj := increasecreditafterremittance(); l_children := dbms_xmldom.getchildnodes(p_node); l_length := dbms_xmldom.getlength(l_children); FOR l_i IN 0 .. (l_length - 1) LOOP l_child := dbms_xmldom.item(l_children, l_i); IF dbms_xmldom.getnodetype(l_child) != dbms_xmldom.element_node THEN CONTINUE; END IF; l_name := dbms_xmldom.getlocalname(dbms_xmldom.makeelement(l_child)); IF l_name = 'LeagueCompanyId' THEN l_decode_result := decode_string(l_child); l_obj.leaguecompanyid := l_decode_result; END IF; IF l_name = 'CompanyId' THEN l_decode_result := decode_string(l_child); l_obj.companyid := l_decode_result; END IF; IF l_name = 'RemittanceValue' THEN l_decode_result := decode_int(l_child); l_obj.remittancevalue := l_decode_result; END IF; IF l_name = 'RemittanceToken' THEN l_decode_result := decode_string(l_child); l_obj.remittancetoken := l_decode_result; END IF; IF l_name = 'RemittanceDateTime' THEN l_decode_result := decode_string(l_child); l_obj.remittancedatetime := l_decode_result; END IF; IF l_name = 'Remark' THEN l_decode_result := decode_string(l_child); l_obj.remark := l_decode_result; END IF; END LOOP; RETURN l_obj; END; END soapdeccommon;
4:编写测试用例进行测试,如下测试用例:
declare request_clob clob :='<ns1:IncreaseCreditAfterRemittance xmlns:ns1="http://tempuri.org/"> <ns1:parameters> <ns1:RemittanceParameterItem> <ns1:LeagueCompanyId>2001116</ns1:LeagueCompanyId> <ns1:CompanyId>1000</ns1:CompanyId> <ns1:RemittanceValue>65000.0</ns1:RemittanceValue> <ns1:RemittanceToken>9591503</ns1:RemittanceToken> <ns1:RemittanceDateTime>2018-09-26T14:51:22.0Z</ns1:RemittanceDateTime> <ns1:Remark>640001391210002018</ns1:Remark> </ns1:RemittanceParameterItem> </ns1:parameters> </ns1:IncreaseCreditAfterRemittance>'; req_doc DBMS_XMLDOM.domdocument; requestNode XMLDOM.domnode; l_request increasecreditafterremittance; begin l_request := increasecreditafterremittance(); req_doc := dbms_xmldom.newDOMDocument (request_clob); requestNode := XMLDOM.item (xmldom.getelementsbytagname (req_doc,'RemittanceParameterItem'), 0); l_request := soapdeccommon.decd_incr_creditafremittance(requestNode); raise_application_error(-20201,'l_request.LeagueCompanyId:'||l_request.leaguecompanyid||'--'||'l_request.CompanyId:'||l_request.CompanyId||'--'||'l_request.RemittanceValue:'||l_request.RemittanceValue); end;
PLSQL DEVELOPER运行测试用例,得出如下图所示结果:
5:经过上述测试,则对于接收来自调用者的xml信息,解析并进行数据库相关操作,如下存储过程功能即:解析接收的xml,对其进行分析,然后插入相关数据库表中
CREATE OR REPLACE PROCEDURE incrcreditafremittance_read(p_request_clob IN CLOB, p_code IN OUT NUMBER, p_err_mesg IN OUT VARCHAR2) AS ------------------------------------------------ --author:xy --date:20181009 --description:获取RFC接口下发的电子付款单,向公司收款单中写入 ------------------------------------------------ req_doc dbms_xmldom.domdocument; requestnode xmldom.domnode; l_request increasecreditafterremittance; v_table_id ad_table.id%TYPE; --公司收款单g_receive表的id v_docno g_receive.docno%TYPE; ----公司收款单g_receive单据编号 v_g_receive_id g_receive.id%TYPE; BEGIN p_code := 1; p_err_mesg := 'FAILED:INSERTION FAILED'; l_request := increasecreditafterremittance(); req_doc := dbms_xmldom.newdomdocument(p_request_clob); requestnode := xmldom.item(xmldom.getelementsbytagname(req_doc, 'RemittanceParameterItem'), 0); l_request := soapdeccommon.decd_incr_creditafremittance(requestnode); --获取表g_receive的id SELECT id INTO v_table_id FROM ad_table WHERE NAME = upper('g_receive'); --自动生成单据编号 SELECT t.sequencename INTO v_docno FROM ad_column t WHERE t.ad_table_id = v_table_id AND t.dbname = 'DOCNO'; v_docno := get_sequenceno(v_docno, 37); v_g_receive_id := get_sequences('G_RECEIVE'); /*raise_application_error(-20201, to_number(REPLACE(substr(l_request.remittancedatetime, 1, 10), '-', '')));*/ INSERT INTO g_receive (id, ad_client_id, ad_org_id, docno, billdate, g_company_id, g_acc_company_id, c_currency_id, c_tranrency_id, g_acctype_id, feereceive, description, status, ownerid, modifierid, creationdate, statuserid, statustime, modifieddate, isactive) SELECT v_g_receive_id, 37, 27, v_docno, to_number(REPLACE(substr(l_request.remittancedatetime, 1, 10), '-', '')), gc.id, gc1.id, cur.id, cur.id, gac.id, l_request.remittancevalue, l_request.remark, 1, 893, 893, SYSDATE, NULL, NULL, SYSDATE, 'Y' FROM dual JOIN g_company gc ON (gc.sap_code = l_request.leaguecompanyid) JOIN g_company gc1 ON (gc1.sap_code = l_request.companyid) JOIN c_currency cur ON (cur.iso_code = 'CNY') JOIN g_acctype gac ON (gac.code = '001' AND gac.name = '默认账户'); IF SQL%ROWCOUNT > 0 THEN g_receive_submit(v_g_receive_id, p_code, p_err_mesg); p_code := 0; p_err_mesg := 'SUCCESS'; END IF; EXCEPTION WHEN OTHERS THEN p_code := 1; p_err_mesg := 'FAILED:' || SQLERRM; END;