简体   繁体   English

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

[英]Parsing only valid xml in Oracle Stored Procedure

I have done a bit of searching and can't quite find a similar scenario to what I am trying to do. 我做了一些搜索,但找不到与我尝试做的相似的情况。

I have the following code that first builds a cursor that is filled up with 1) xml 2) id. 我有以下代码,该代码首先构建一个游标,该游标填充有1)xml 2)id。

This works fine until bad xml row is hit (in the second select statement) then it breaks the procedure and does not continue. 直到在第二个select语句中击中了错误的xml行之后,此方法才能正常工作,然后它中断了该过程且不再继续。 I need to find a way to skip bad xml in the second select statement and continue building the cursor. 我需要找到一种方法来跳过第二个select语句中的错误xml并继续构建游标。

Here is the code: 这是代码:

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;

For those that wanted an answer to this here it is. 对于那些想要解决这个问题的人。

I first created a new function: 我首先创建了一个新函数:

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;

This is the main function which utilities this utility. 这是使用该实用程序的主要功能。

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM