【问题标题】:Oracle XMLQUERY: How to find an XML node to remove based on sub-node properties?Oracle XMLQUERY:如何根据子节点属性找到要删除的 XML 节点?
【发布时间】:2020-11-13 04:08:11
【问题描述】:

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

我有以下代码:

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] 是要删除的硬编码值。实际上,我需要删除包含&lt;CONTYPE&gt;2&lt;/CONTYPE&gt;&lt;CON*_LIST_ITEM&gt; 节点(* 是某个数字)。

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

【问题讨论】:

    标签: xml oracle oracle-xml-db


    【解决方案1】:

    您可以通过正则表达式及其子节点CONTYPE过滤所有子节点的名称: //*[fn:matches(name(),"^CON\D+_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(),"^CON\D+_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;
    /
    

    【讨论】:

    • 太棒了!我已经做好了“这无法做到”或充其量是沉默的准备。你摇滚。我需要学习 XQuery :-)
    猜你喜欢
    • 1970-01-01
    • 2017-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 2021-08-28
    • 1970-01-01
    相关资源
    最近更新 更多