oracle存儲過程解析xml實例

說明:入參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;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章