检查 XMLType 节点值并在必要时更新

Check XMLType node value and update if necessary

我有一个像这样的简单 xml:

<Parameters>
 <Parameter>
  <Index>0</Index>
  <Name>Date</Name>
  <Value>@Today</Value>
 </Parameter>
 <Parameter>
  <Index>1</Index>
  <Name>Id</Name>
  <Value>22</Value>
 </Parameter>
</Parameters>

我想遍历每个参数,如果值以“@”开头,则调用一个函数,该函数将值作为参数,returns 一个新值。
使用新值更新 xml.
我找到了如何使用更新xml,但没有运气如何实现我的场景。

您可以通过每个参数节点循环执行,通过函数更改值(我的代码中的内部 CheckXmlValue)-

declare
  cur_xml  sys_refcursor;
  v_val varchar2(3000);
  n_val varchar2(3000);
  xml_     XMLType := XMLType(
        '<Parameters>
         <Parameter>
          <Index>0</Index>
          <Name>Date</Name>
          <Value>@Today</Value>
         </Parameter>
         <Parameter>
          <Index>1</Index>
          <Name>Id</Name>
          <Value>22</Value>
         </Parameter>
        </Parameters>'
);
    function CheckXmlValue(val_ in varchar2) return varchar2 is
    begin
        return 
            case lower(val_)
                when '@today' then to_char(sysdate, 'dd/mm/yyyy')
                when '@yesterday' then to_char(sysdate-1, 'dd/mm/yyyy')
                else val_
            end;
    end;
begin
  open cur_xml for
    select extractValue(column_value, '//Value') str
      from table(XMLSequence(extract(xml_, '/Parameters/Parameter')));
  loop
    fetch cur_xml into v_val;
    n_val := CheckXmlValue(v_val);
    exit when cur_xml%notfound;
    select updateXml (
                xml_,
                '//Parameters/Parameter/Value[text()="'||v_val||'"]/text()',
                n_val
           )
    into xml_
    from DUAL;
  end loop;
  close cur_xml;
  -- result:
  dbms_output.put_line(xml_.extract('*').getStringVal());
end;
/

这个怎么样?如果在 PL*SQL 中使用,只需使用函数即可。

  select updatexml(xmltype('<Parameters>
         <Parameter>
          <Index>0</Index>
          <Name>Date</Name>
          <Value>@Today</Value>
         </Parameter>
         <Parameter>
          <Index>1</Index>
          <Name>Id</Name>
          <Value>22</Value>
         </Parameter>
        </Parameters>'), '/Parameters/Parameter/Value[text()="@Today"]', to_char(sysdate, 'dd/mm/yyyy')) 
from dual;

注意是我调用的函数,需要的话换成你自己的。

对于许多不同的变体,只需在 upatexml 中添加一个又一个这样的更改,例如:

  select updatexml(xmltype('<Parameters>
         <Parameter>
          <Index>0</Index>
          <Name>Date</Name>
          <Value>@Today</Value>
         </Parameter>
         <Parameter>
          <Index>1</Index>
          <Name>Id</Name>
          <Value>22</Value>
         </Parameter>
         <Parameter>
          <Index>2</Index>
          <Name>Id</Name>
          <Value>@Yesterday</Value>
         </Parameter>
        </Parameters>'), '/Parameters/Parameter/Value[text()="@Today"]/text()'    , to_char(sysdate    , 'dd/mm/yyyy')
                       , '/Parameters/Parameter/Value[text()="@Yesterday"]/text()', to_char(sysdate - 1, 'dd/mm/yyyy')) 
from dual;