在Oracle存储过程中仅解析有效的xml

时间:2016-03-22 01:44:38

标签: sql plsql oracle11g

我做了一些搜索,并且找不到与我想做的事情类似的情况。

我有以下代码,首先构建一个填充的游标 1)xml 2)id。

这可以正常工作,直到命中错误的xml行(在第二个select语句中)然后它会中断该过程并且不会继续。我需要找到一种方法来跳过第二个select语句中的错误xml并继续构建游标。

以下是代码:

DECLARE
COUNTER NUMBER;

CURSOR CXD_ID_UPDATE IS
    WITH
XMLDATA
   AS
(
SELECT XMLTYPE(X.XMLDOC) XMLD, X.CXD_ID
FROM
   C_XML_DOC X RIGHT OUTER JOIN CPS_POT P ON X.CXD_ID = P.CXD_ID 
   WHERE P.CXD_ID IS NOT NULL
)
SELECT XT.SCAN_DOC_ID AS SCAN_DOC_ID
,X.CXD_ID AS CXD_ID
FROM XMLDATA X, CPS_DOCUMENT DOC,
 XMLTABLE('/HXML/BATCH/FOLDER/DOCUMENTS/DOCUMENT'
 PASSING X.XMLD
 COLUMNS SCAN_DOC_ID VARCHAR2(50) PATH '@ScanDocID') XT
 WHERE REGEXP_LIKE(XT.SCAN_DOC_ID,'^\d+(\.\d+)?$', '')
AND XT.SCAN_DOC_ID = DOC.DOC_ID;
BEGIN
COUNTER := 0;
FOR REC IN CXD_ID_UPDATE
LOOP   
BEGIN
  UPDATE DOCUMENT SET CXD_ID = REC.CXD_ID WHERE DOC_ID = REC.SCAN_DOC_ID ; 
  COUNTER := COUNTER + 1;

  EXCEPTION WHEN OTHERS THEN
     CONTINUE; 
  END;
 END LOOP;
 DBMS_OUTPUT.PUT_LINE('UPDATED: ' || COUNTER || ' DOCUMENTS' );
END;

1 个答案:

答案 0 :(得分:0)

对于那些想要在这里得到答案的人来说。

我首先创建了一个新函数:

create or replace function isWellFormedXML(P_XML_CONTENT CLOB,         
P_ERROR_MESSAGE OUT VARCHAR2)
return number
as
  PARSING_ERROR exception;
  PRAGMA EXCEPTION_INIT( PARSING_ERROR , -31011 );
  V_VALID_XML XMLTYPE;
begin
  V_VALID_XML := XMLTYPE(P_XML_CONTENT);
  V_VALID_XML := NULL;
 return 1;
 exception
 when PARSING_ERROR then
   P_ERROR_MESSAGE := DBMS_UTILITY.FORMAT_ERROR_STACK() ||          DBMS_UTILITY.FORMAT_ERROR_BACKTRACE();
   return 0;
 when others then
   RAISE;
 end;

这是实用程序的主要功能。

DECLARE
 V_ERROR_MSG VARCHAR2(4000);
 COUNTER NUMBER(10);
BEGIN
COUNTER := 0;
FOR R IN (  
SELECT X.CXD_ID CXD,
   X.XMLDOC XML FROM XML_DOC X, POT P WHERE P.CXD_ID = X.CXD_ID
 ) LOOP   
 BEGIN
  IF(isWellFormedXML(R.XML,V_ERROR_MSG)) = 1 THEN
      FOR L IN (
        SELECT D.SCAN_DOC_ID DOCID
        FROM DOCUMENT DOC, xmltable
         ('/HXML/BATCH/FOLDER/DOCUMENTS/DOCUMENT'
            PASSING XMLTYPE.CREATEXML(R.XML)
           COLUMNS SCAN_DOC_ID VARCHAR2(50) PATH '@ScanDocID'  
         ) D  
         WHERE REGEXP_LIKE(D.SCAN_DOC_ID,'^\d+(\.\d+)?$', '')
         AND D.SCAN_DOC_ID = DOC.DOC_ID 
      ) LOOP
      BEGIN
       COUNTER := COUNTER + 1; 
       --DBMS_OUTPUT.put_line('CXD '|| R.CXD || ' DOCID ' || L.DOCID);  
      END;
      END LOOP; 
  END IF;   
  EXCEPTION
     WHEN no_data_found THEN
      NULL;
  END;
END LOOP;     
DBMS_OUTPUT.put_line('TOTAL NUMBER OF DOCUMENTS : ' || COUNTER);
END;