Oracle XMLQUERY:如何根据子节点属性找到要删除的XML节点



你能帮我让下面的代码更健壮并避免硬编码吗?

我有以下代码:

SET SERVEROUTPUT ON SIZE UNLIMITED;
exec DBMS_OUTPUT.ENABLE (NULL);
set lines 1000
set define OFF
DECLARE
  l_xml   VARCHAR2(32767);
BEGIN
         l_XML:='<?xml version="1.0"?>              ';
  l_XML:=l_XML||'<ROWSET>                           ';
  l_XML:=l_XML||' <ROW>                             ';
  l_XML:=l_XML||'  <TABLE_T>                        ';
  l_XML:=l_XML||'   <VERS_MAJOR>2</VERS_MAJOR>      ';
  l_XML:=l_XML||'   <CON0_LIST>                     ';
  l_XML:=l_XML||'    <CON0_LIST_ITEM>               ';
  l_XML:=l_XML||'     <NAME>FAC2TS</NAME>           ';
  l_XML:=l_XML||'     <CONTYPE>7</CONTYPE>          ';
  l_XML:=l_XML||'    </CON0_LIST_ITEM>              ';
  l_XML:=l_XML||'   </CON0_LIST>                    ';
  l_XML:=l_XML||'   <PROPERTY1>536870944</PROPERTY1>';
  l_XML:=l_XML||'   <CON2_LIST>                     ';
  l_XML:=l_XML||'    <CON2_LIST_ITEM>               ';
  l_XML:=l_XML||'     <NAME>FACTS_PK</NAME>         ';
  l_XML:=l_XML||'     <CONTYPE>3</CONTYPE>          ';
  l_XML:=l_XML||'    </CON2_LIST_ITEM>              ';
  l_XML:=l_XML||'   </CON2_LIST>                    ';
  l_XML:=l_XML||'   <PROPERTY>536870944</PROPERTY>  ';
  l_XML:=l_XML||'   <CON1_LIST>                     ';
  l_XML:=l_XML||'    <CON1_LIST_ITEM>               ';
  l_XML:=l_XML||'     <NAME>FACTS_PK</NAME>         ';
  l_XML:=l_XML||'     <CONTYPE>2</CONTYPE>          ';
  l_XML:=l_XML||'    </CON1_LIST_ITEM>              ';
  l_XML:=l_XML||'   </CON1_LIST>                    ';
  l_XML:=l_XML||'   <REFPAR_LEVEL>0</REFPAR_LEVEL>  ';
  l_XML:=l_XML||'  </TABLE_T>                       ';
  l_XML:=l_XML||' </ROW>                            ';
  l_XML:=l_XML||'</ROWSET>                          ';
   
   SELECT  XMLSERIALIZE( CONTENT 
                         XMLQUERY( 'copy $i := $p modify delete nodes $i/ROWSET[1]/ROW[1]/TABLE_T[1]/CON1_LIST[1] return $i'
                                   PASSING XMLTYPE(l_XML) AS "p" 
                                   RETURNING CONTENT
                                 ) 
                         INDENT SIZE=2
                       )
      INTO l_xml
   FROM dual;
   DBMS_OUTPUT.PUT_Line(l_XML);
END;

/ROWSET[1]/ROW[1]/TABLE_T[1]/CON1_LIST[1]是要删除的硬编码值。实际上,我需要删除包含<CONTYPE>2</CONTYPE><CON*_LIST_ITEM>节点(*是某个数字(。

你能帮助XMLQUERY完成这项工作吗?

您可以通过正则表达式及其子节点CONTYPE过滤所有子节点的名称://*[fn:matches(name(),"^COND+_LIST$") and ./*/CONTYPE="2"]

完整示例:

DECLARE
  l_xml   VARCHAR2(32767);
BEGIN
         l_XML:='<?xml version="1.0"?>              ';
  l_XML:=l_XML||'<ROWSET>                           ';
  l_XML:=l_XML||' <ROW>                             ';
  l_XML:=l_XML||'  <TABLE_T>                        ';
  l_XML:=l_XML||'   <VERS_MAJOR>2</VERS_MAJOR>      ';
  l_XML:=l_XML||'   <CON0_LIST>                     ';
  l_XML:=l_XML||'    <CON0_LIST_ITEM>               ';
  l_XML:=l_XML||'     <NAME>FAC2TS</NAME>           ';
  l_XML:=l_XML||'     <CONTYPE>7</CONTYPE>          ';
  l_XML:=l_XML||'    </CON0_LIST_ITEM>              ';
  l_XML:=l_XML||'   </CON0_LIST>                    ';
  l_XML:=l_XML||'   <PROPERTY1>536870944</PROPERTY1>';
  l_XML:=l_XML||'   <CON2_LIST>                     ';
  l_XML:=l_XML||'    <CON2_LIST_ITEM>               ';
  l_XML:=l_XML||'     <NAME>FACTS_PK</NAME>         ';
  l_XML:=l_XML||'     <CONTYPE>3</CONTYPE>          ';
  l_XML:=l_XML||'    </CON2_LIST_ITEM>              ';
  l_XML:=l_XML||'   </CON2_LIST>                    ';
  l_XML:=l_XML||'   <PROPERTY>536870944</PROPERTY>  ';
  l_XML:=l_XML||'   <CON1_LIST>                     ';
  l_XML:=l_XML||'    <CON1_LIST_ITEM>               ';
  l_XML:=l_XML||'     <NAME>FACTS_PK</NAME>         ';
  l_XML:=l_XML||'     <CONTYPE>2</CONTYPE>          ';
  l_XML:=l_XML||'    </CON1_LIST_ITEM>              ';
  l_XML:=l_XML||'   </CON1_LIST>                    ';
  l_XML:=l_XML||'   <REFPAR_LEVEL>0</REFPAR_LEVEL>  ';
  l_XML:=l_XML||'  </TABLE_T>                       ';
  l_XML:=l_XML||' </ROW>                            ';
  l_XML:=l_XML||'</ROWSET>                          ';
   
   SELECT 
      XMLSERIALIZE( 
         CONTENT 
             XMLQUERY( 
                 'copy $i := $p 
                  modify 
                  delete nodes 
                     $i//*[fn:matches(name(),"^COND+_LIST$") and ./*/CONTYPE="2"]
                  return $i'
                 PASSING XMLTYPE(l_XML) AS "p" 
                 RETURNING CONTENT
             ) 
             INDENT SIZE=2
           )
      INTO l_xml
   FROM dual;
   DBMS_OUTPUT.PUT_Line(l_XML);
END;
/

最新更新