本篇实例基于《PLSQL解析XML示例1》中的type IncreaseCreditAfterRemittance进行构造XML。
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.考虑到构造XML过程中使用到oracle包程序DBMS_XMLDOM中的类型DOMDocument特殊型,现将其封装在新定义的包中,定义如下XmlResponse:
CREATE OR REPLACE PACKAGE XmlResponse IS response_doc DBMS_XMLDOM.DOMDocument ; END XmlResponse ; CREATE OR REPLACE PACKAGE BODY XmlResponse IS END XmlResponse ;
3:定义公共构造XML包程序:SoapEncCommon,将构造公共具体类型标签的方法和特定XML构造程序封装在其中,方便代码复用,便于维护。包程序如下:
CREATE OR REPLACE PACKAGE SoapEncCommon IS ------------------------------------ --author:xy --date:20181009 --description:用于构造XML中具体类型字段 ------------------------------------ FUNCTION encode_string (p_obj IN VARCHAR2 , p_tag IN VARCHAR2 ) RETURN DBMS_XMLDOM.DOMNode ; FUNCTION encode_int (p_obj IN INTEGER , p_tag IN VARCHAR2 ) RETURN DBMS_XMLDOM.DOMNode ; FUNCTION encode_calendar (p_obj IN TIMESTAMP WITH TIME ZONE, p_tag IN VARCHAR2 ) RETURN DBMS_XMLDOM.DOMNode ; FUNCTION encode_integer (p_obj IN INTEGER , p_tag IN VARCHAR2 ) RETURN DBMS_XMLDOM.DOMNode ; FUNCTION encd_incr_creditafremittance(p_obj IN increasecreditafterremittance ) RETURN DBMS_XMLDOM.DOMDocument; FUNCTION encode_response(p_obj IN increasecreditafterremittance,p_tag IN VARCHAR2) RETURN DBMS_XMLDOM.DOMNode; END SoapEncCommon ; CREATE OR REPLACE PACKAGE BODY SoapEncCommon IS ------------------------------------ --author:xy --date:20181009 --description:用于构造XML中具体类型字段 ------------------------------------ FUNCTION encode_string (p_obj IN VARCHAR2 , p_tag IN VARCHAR2 ) RETURN DBMS_XMLDOM.DOMNode IS l_return_node DBMS_XMLDOM.DOMNode ; l_node4 DBMS_XMLDOM.DOMNode ; BEGIN l_node4 := DBMS_XMLDOM.makeNode (DBMS_XMLDOM.createElement (XmlResponse.response_doc , p_tag )); IF p_obj IS NOT NULL THEN BEGIN l_return_node := DBMS_XMLDOM.appendChild (l_node4 , DBMS_XMLDOM. makeNode (DBMS_XMLDOM.createTextNode (XmlResponse.response_doc , p_obj ))); END; ELSE BEGIN l_return_node := DBMS_XMLDOM.appendChild (l_node4 , DBMS_XMLDOM.makeNode (DBMS_XMLDOM.createTextNode (XmlResponse.response_doc , ' '))); END; END IF; RETURN l_node4 ; END; FUNCTION encode_int (p_obj IN INTEGER , p_tag IN VARCHAR2 ) RETURN DBMS_XMLDOM.DOMNode IS BEGIN IF p_obj IS NOT NULL THEN BEGIN RETURN encode_string (TO_CHAR (p_obj ), p_tag ); END; ELSE BEGIN RETURN encode_string (' ', p_tag ); END; END IF; END; FUNCTION encode_calendar (p_obj IN TIMESTAMP WITH TIME ZONE, p_tag IN VARCHAR2 ) RETURN DBMS_XMLDOM.DOMNode IS BEGIN RETURN encode_string (TO_CHAR (p_obj , 'YYYY-MM-DD"T"HH24:MI:SSTZH:TZM'), p_tag ); END; FUNCTION encode_integer (p_obj IN INTEGER , p_tag IN VARCHAR2 ) RETURN DBMS_XMLDOM.DOMNode IS BEGIN IF p_obj IS NOT NULL THEN BEGIN RETURN encode_string (TO_CHAR (p_obj ), p_tag ); END; ELSE BEGIN RETURN encode_string (' ', p_tag ); END; END IF; END; FUNCTION encode_response(p_obj IN increasecreditafterremittance,p_tag IN VARCHAR2) RETURN DBMS_XMLDOM.DOMNode IS l_element_1 DBMS_XMLDOM.DOMElement ; l_return_node DBMS_XMLDOM.DOMNode ; l_element DBMS_XMLDOM.DOMElement ; l_node0 DBMS_XMLDOM.DOMNode ; l_node1 DBMS_XMLDOM.DOMNode ; l_node2 DBMS_XMLDOM.DOMNode ; l_node3 DBMS_XMLDOM.DOMNode ; l_node4 DBMS_XMLDOM.DOMNode ; BEGIN l_element := DBMS_XMLDOM.createElement (XmlResponse.response_doc , 'ns1:parameters'); l_node1 := DBMS_XMLDOM.makeNode (l_element ); BEGIN l_element_1 := DBMS_XMLDOM.createElement (XmlResponse.response_doc , 'ns1:RemittanceParameterItem'); l_node2 := DBMS_XMLDOM.makeNode (l_element_1 ); END; BEGIN IF p_obj.leaguecompanyid IS NOT NULL THEN l_return_node := DBMS_XMLDOM.appendChild (l_node2, encode_string (p_obj.leaguecompanyid , 'ns1:LeagueCompanyId')); END IF; IF p_obj.companyid IS NOT NULL THEN l_return_node := DBMS_XMLDOM.appendChild (l_node2, encode_string (p_obj.companyid , 'ns1:CompanyId')); END IF; IF p_obj.remittancevalue IS NOT NULL THEN l_return_node := DBMS_XMLDOM.appendChild (l_node2, encode_string (p_obj.remittancevalue , 'ns1:RemittanceValue')); END IF; IF p_obj.remittancetoken IS NOT NULL THEN l_return_node := DBMS_XMLDOM.appendChild (l_node2, encode_string (p_obj.remittancetoken , 'ns1:RemittanceToken')); END IF; IF p_obj.remittancedatetime IS NOT NULL THEN l_return_node := DBMS_XMLDOM.appendChild (l_node2, encode_string (p_obj.remittancedatetime , 'ns1:RemittanceDateTime')); END IF; IF p_obj.remark IS NOT NULL THEN l_return_node := DBMS_XMLDOM.appendChild (l_node2, encode_string (p_obj.remark , 'ns1:Remark')); END IF; END; BEGIN l_return_node := DBMS_XMLDOM.appendChild (l_node1 , l_node2); END; BEGIN l_element := DBMS_XMLDOM.createElement (XmlResponse.response_doc , p_tag ); l_node0 := DBMS_XMLDOM.makeNode (l_element ); l_return_node := DBMS_XMLDOM.appendChild (l_node0, l_node1 ); END; RETURN l_node0 ; END; FUNCTION encd_incr_creditafremittance(p_obj IN increasecreditafterremittance ) RETURN DBMS_XMLDOM.DOMDocument IS l_response_node DBMS_XMLDOM.DOMNode ; l_element DBMS_XMLDOM.DOMElement ; l_node DBMS_XMLDOM.DOMNode ; l_fcall_tmp DBMS_XMLDOM.DOMNode ; BEGIN XmlResponse.response_doc := DBMS_XMLDOM.newDOMDocument (); l_response_node := encode_response(p_obj , 'ns1:IncreaseCreditAfterRemittance'); l_element := DBMS_XMLDOM.makeElement (l_response_node ); l_node := DBMS_XMLDOM.makeNode (XmlResponse.response_doc ); l_fcall_tmp := DBMS_XMLDOM.appendChild (l_node , l_response_node ); DBMS_XMLDOM.setAttribute (l_element , 'xmlns:ns1', 'http://tempuri.org/'); RETURN XmlResponse.response_doc ; END; END SoapEncCommon ;
4.编写测试用例,来验证构造XML程序功能是否正确,测试用例如下:
DECLARE l_request increasecreditafterremittance; responseDoc DBMS_XMLDOM.DOMDOCUMENT; l_xmltype XMLTYPE; response_clob clob; begin l_request := increasecreditafterremittance(); l_request.leaguecompanyid := '2001116'; l_request.companyid := '1000'; l_request.remittancevalue := '6500.0'; l_request.remittancetoken := '9591503'; l_request.remittancedatetime := '2018-09-26T14:51:22.0Z'; l_request.remark := '640001391210002018'; responseDoc := SoapEncCommon.encd_incr_creditafremittance(l_request); l_xmltype := dbms_xmldom.getXmlType(responseDoc); dbms_xmldom.freeDocument(responseDoc); response_clob := l_xmltype.getClobVal; raise_application_error(-20201,'response xml:'||response_clob); end;
测试运行结果如下所示:
5.以上只是针对简单的XML构造做简单的展示,若要构造复杂的XML格式数据,如:带嵌套循环的格式数据,其实也不难,只需根据对应的循环标签的特征,在类型中新增用于存储循环标签值的变量(成员),并且在特定构造程序中循环遍历此变量,循环依次追加相同标签不同值的XML格式数据。