oracle存储过程解析xml实例

该Oracle存储过程接收一个XML字符串作为输入,并将其解析为DOM文档。过程中涉及到XML校验、数据提取、日志记录以及事务管理。通过遍历XML节点,将数据处理并更新到ZH_KSDMTYPE类型的自定义表中。

说明:入参xml_in 为xml字符串

          出参package.cursor为自定义包的类型

         变量ZH_KSDMTYPE为自定义表类型,该类型定义时需要实现类型体(type bodies)

CREATE OR REPLACE PROCEDURE ZH_PLATFORM_DEPART (xml_in IN CLOB, v_cur OUT package.cursor)
AS
  ---xml解析为doc
    xmlp xmlparser.parser;
    xml_doc xmldom.DOMDocument;
    doc_node xmldom.DOMNode;
    doc_nodelist xmldom.DOMNodeList;
    doc_len number;
    ---信息
    Info_Nodel xmldom.DOMNodeList;
    Info_No xmldom.DOMNode;
    Info_Len number;
    test_xml CLOB;
    ---子元素
    child_node xmldom.DOMNode;
    child_NodeList xmldom.DOMNodeList;
    child_len number;
    nnm xmldom.DOMNamedNodeMap;   --暂存row数据map
    v_coluValue varchar2(4000); ---最小节点值
    v_nodeName  varchar2(100);  --最小节点名称
    n_maxFid number(18); --日志ID
    Log_ygbh VARCHAR2(20);
    n_rollback number(2); --回滚点
    v_Sqlerrm varchar2(1000); --错误
    Ret_MSG varchar2(1000); 
    ---自定义错误 20000 操作成功 20001 校验失败  20002 不能为空  20003 已存在  20004 获取失败
    EXCEPTION_ERR EXCEPTION;
    ERR_TEXT varchar2(1000);---错误
    ERR_CODE number(18);  ---自定义错误号:20000-20999
    --科室代码表结构变量
    Zh_KSDM  ZH_KSDMTYPE :=ZH_KSDMTYPE(0);
    
BEGIN
    --测试用
  select clob_xml into test_xml from  test_clob where  clob_id=1;
  --先保存到日志表
  --获取主键
  gf_get_max('ZH_PROXML',1,n_maxFid);
  n_rollback :=1;
  Savepoint tran_one; --开始事务
      insert into ZH_PROXML(fid,czgh,czdate,funcode,funname,fxmlin) --,fxmlin,fxmlout,mzhm
      values(n_maxFid,'回写',sysdate,'B0004','此为日志',test_xml);
  commit ;
    n_rollback :=0;
    --xml解析
    xmlp := xmlparser.newparser;
    xmlparser.parseclob(xmlp,test_xml);  --- 测试  test_xml  正式 xml_in
    --xml转换为doc
    xml_doc := xmlparser.getDocument(xmlp);
    xmlparser.freeparser(xmlp);
    
    Info_Nodel := xmldom.getElementsByTagName(xml_doc,'INFO');
    Info_Len :=xmldom.getLength(Info_Nodel);
    --取出第一个 INFO 
    Info_No:=xmldom.item(Info_Nodel,0);
    Info_Nodel := xmldom.getChildNodes(Info_No);
    Info_Len := xmldom.getLength(Info_Nodel);
    for w in 0.. Info_Len-1 loop
            Info_No:=xmldom.item(Info_Nodel,w);
            v_coluValue := xmldom.getNodeValue(xmldom.getFirstChild(Info_No));
            v_nodeName :=xmldom.getNodeName(Info_No);
            if v_nodeName = 'INFOID' then
                    IF v_coluValue <> 'B0004' then
                                 ERR_TEXT := 'XML校验失败!';
                                 ERR_CODE :=20001;
                                 raise EXCEPTION_ERR;
                    end if;
             end if;
             if v_nodeName = 'EMPNUM' then
                            Log_ygbh :=v_coluValue;
             end if;
    end loop;
 ---取出所有row元素
    doc_nodelist := xmldom.getElementsByTagName(xml_doc,'ROW');
    doc_len :=xmldom.getLength(doc_nodelist);
    n_rollback :=2;
  Savepoint tran_two; --开始事务
  for i in 0.. doc_len-1 loop
             --取出第i个row元素
      doc_node:=xmldom.item(doc_nodelist,i);
            child_NodeList := xmldom.getChildNodes(doc_node);
            child_len := xmldom.getLength(child_NodeList);
            for k in 0..child_len-1 loop
                    --取出第i 个结点
                    child_node := xmldom.item(child_NodeList,k);
                    --节点名称
                    v_nodeName :=xmldom.getNodeName(child_node); 
                    --节点值
                    v_coluValue := xmldom.getNodeValue(xmldom.getFirstChild(child_node));
                    if v_nodeName = 'DEPARTNUM' then  --科室代码
                            
                    end if;
            END LOOP;
            ---更新或插入
    
  END LOOP;
    v_Sqlerrm:=Sqlerrm||dbms_utility.format_error_backtrace();
    update ZH_PROXML set msg=v_Sqlerrm where fid = n_maxFid;
    ERR_TEXT := '成功!';
    ERR_CODE :=20000;
    Ret_MSG := to_char(ERR_CODE)||'-'||ERR_TEXT;   ---Log_ygbh
    update ZH_PROXML set sqlerr=v_Sqlerrm ,msg=Ret_MSG,czgh=nvl(Log_ygbh,czgh) where fid = n_maxFid;
    commit;
    xmldom.freeDocument(xml_doc);
    Open v_cur For
                Select ERR_TEXT As msg,ERR_CODE as msgcode From dual;
    return;
    
EXCEPTION
when EXCEPTION_ERR then
    if n_rollback = 1 then
        rollback to tran_one;
    else
        if n_rollback = 2 then
             rollback to tran_two;
        end if;
    end if;
    Ret_MSG := to_char(ERR_CODE)||'-'||ERR_TEXT;
    update ZH_PROXML set msg=Ret_MSG,czgh=nvl(Log_ygbh,czgh) where fid = n_maxFid;
    commit;
    Open v_cur For
            Select ERR_TEXT As msg,ERR_CODE as msgcode From dual;
    return;
When others Then
    if n_rollback = 1 then
            rollback to tran_one;
    else
            if n_rollback = 2 then
                 rollback to tran_two;
            end if;
    end if;
    v_Sqlerrm:=Sqlerrm||dbms_utility.format_error_backtrace();
    ERR_CODE :=sqlcode;
    update ZH__PROXML set sqlerr=v_Sqlerrm  where fid = n_maxFid;
    Open v_cur For
            Select v_Sqlerrm As msg,ERR_CODE  as msgcode From dual;
    return;
END;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值