Проверьте значение узла XMLType и при необходимости обновите

У меня есть такой простой 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>

Я хотел бы перебрать каждый параметр, и если значение начинается с '@', вызывается функция, которая принимает в качестве параметра значение и возвращает новое значение.
Используйте новое значение для обновления xml.
Я нашел как использовать updatexml, но не повезло, как реализовать мой сценарий.


person Nianios    schedule 08.12.2015    source источник
comment
У меня есть функция, которая принимает это значение (@today - ›вернуть сегодня значение 08/12/2015, @ вчера-› возвращает 07/12/2015 и т. Д.)   -  person Nianios    schedule 08.12.2015


Ответы (2)


Как насчет этого? При использовании в 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;
person Mathias Magnusson    schedule 14.12.2015
comment
Я еще не пробовал, но у меня нет только @Today в качестве флага, у меня есть около двадцати таких флагов (@ Yesterday, @ LastMonth и т. Д.) Так что мне нужно проверить, начинается ли он с @. Любое решение для этого? - person Nianios; 14.12.2015
comment
Я добавил блок, показывающий, как внести несколько изменений. - person Mathias Magnusson; 14.12.2015
comment
Спасибо, когда я запускаю ваш код, в новом xml отсутствует значение - person Nianios; 14.12.2015
comment
Я нашел это. Нам нужно добавить / текст в конец пути. Таким образом, он будет выглядеть следующим образом: '/ Parameters / Parameter / Value [text () = @ Today] / text' Не могли бы вы обновить свой ответ, чтобы я мог его принять? - person Nianios; 14.12.2015
comment
Он работает так, как я написал в моей базе данных. наверное разница в разных версиях Oracle. Я обновил его на основе ваших отзывов. - person Mathias Magnusson; 15.12.2015
comment
Просто для справки, если кто-то хочет использовать начало с: '/ Параметры / Параметр / Значение [начинается с (., @)] / Text ()' - person Nianios; 15.12.2015

Вы можете делать это циклически по каждому узлу параметров, изменяя значение по функции (внутренний 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;
/
person Stawros    schedule 10.12.2015