Как решить сложную XMLELEMENT в Oracle - PullRequest
0 голосов
/ 12 ноября 2018

проблема

XML

<logs>
    <log>
        <ID>123456</ID>
        <NAME>TEST</NAME>
    </log>
</logs>
<logs>
    <log>
        <ID>1234567</ID>
        <NAME>TEST1</NAME>
    </log>
</logs>

в приведенных выше XML-журналах закрываются сразу после тега журнала.

Но мне нужен XML, где теги logs закрыты в xml, как указано ниже.

<logs>
    <log>
        <ID>123456</ID>
        <NAME>TEST</NAME>
    </log>
    <log>
        <ID>1234567</ID>
        <NAME>TEST1</NAME>
    </log>
</logs>

код, который я пробовал

v_output - выходная переменная типа clob.

BEGIN
    x := XMLType (in_xml);

    FOR r IN (SELECT EXTRACTVALUE (VALUE (p), '/log/id/text()') AS log_id
                FROM TABLE (XMLSEQUENCE (EXTRACT (x, '/logs/log'))) p)
    LOOP
        OPEN cursorname (r.id);

        FETCH cursorname INTO tmp;

        -- fetching columns
        IF cursorname%FOUND
        THEN
            SELECT XMLELEMENT ("logs",
                               XMLELEMENT ("log", XMLFOREST (id, name))).GETCLOBVAL ()
              INTO out_xml
              FROM  view where id in ( rec1.id ) ;

            v_output := out_xml;
            DBMS_OUTPUT.PUT_LINE (v_output);
        END IF;

        CLOSE cursorname;
    END LOOP;
  • Может кто-нибудь предложить, как я могу решить несколько элементов XML, используя xmlelement.

  • Входные данные - XML, а после синтаксического анализа выходные данные xml должны быть xml.

  • Если у меня есть требование Dyanamic XML, я мог бы использовать код ниже.

    select xmltype(cursor(select * from view )) from dual;
    
  • курсор находится в цикле.

  • Любые предложения приветствуются.

1 Ответ

0 голосов
/ 12 ноября 2018

Если я понимаю, что вы пытаетесь сделать, вы начинаете со строковой версии XML-документа, например:

<logs><log><ID>123456</ID></log><log><ID>1234567</ID></log></logs>

и пытается добавить значение name, соответствующее каждому из этих значений id, которые вы получаете из представления.

Вы можете извлечь все идентификаторы, используя XMLTable, присоединить их к представлению и восстановить окончательный XML с помощью XMLAgg, что-то вроде:

select xmlelement("logs", xmlagg(xmlelement("log", xmlforest(v.id, v.name)))).getclobval()
into out_xml
from xmltable(
  '/logs/log'
  passing xmltype(in_xml)
  columns id number path 'ID'
) x
join your_view v on v.id = x.id;

Как демонстрация в простом SQL, начиная с вашей строки и с CTE для представления вашего представления:

-- CTE to represent your view
with your_view (id, name) as (
  select 123456, 'TEST' from dual
  union all
  select 1234567, 'TEST1' from dual
)
-- actual query
select xmlelement("logs", xmlagg(xmlelement("log", xmlforest(v.id, v.name)))).getclobval()
from xmltable(
  '/logs/log'
  passing xmltype('<logs><log><ID>123456</ID></log><log><ID>1234567</ID></log></logs>')
  columns id number path 'ID'
) x
join your_view v on v.id = x.id;

XMLELEMENT("LOGS",XMLAGG(XMLELEMENT("LOG",XMLFOREST(V.ID,V.NAME)))).GETCLOBVAL()                     
-----------------------------------------------------------------------------------------------------
<logs><log><ID>123456</ID><NAME>TEST</NAME></log><log><ID>1234567</ID><NAME>TEST1</NAME></log></logs>

или сериализовано для его подтверждения:

-- CTE to represent your view
with your_view (id, name) as (
  select 123456, 'TEST' from dual
  union all
  select 1234567, 'TEST1' from dual
)
-- actual query
select xmlserialize(document
  xmlelement("logs", xmlagg(xmlelement("log", xmlforest(v.id, v.name))))
  indent) as out_xml
from xmltable(
  '/logs/log'
  passing xmltype('<logs><log><ID>123456</ID></log><log><ID>1234567</ID></log></logs>')
  columns id number path 'ID'
) x
join your_view v on v.id = x.id;

OUT_XML                                                                         
--------------------------------------------------------------------------------
<logs>
  <log>
    <ID>123456</ID>
    <NAME>TEST</NAME>
  </log>
  <log>
    <ID>1234567</ID>
    <NAME>TEST1</NAME>
  </log>
</logs>

Если вы действительно хотите использовать механизм, показанный в вопросе, с которым вы связались, то вы можете создать окончательный выходной CLOB, добавив каждый элемент, сгенерированный внутри цикла, с добавлением тега start и end logs вне цикла:

declare
  in_xml clob := '<logs><log><ID>123456</ID></log><log><ID>1234567</ID></log></logs>';
  out_xml clob;
  v_output clob;
begin
  v_output := '<logs>';
  for r in (
    select id
    from xmltable(
      '/logs/log'
      passing xmltype(in_xml)
      columns id number path 'ID'
    )
  )
  loop
     select xmlelement("log", xmlforest (id, name)).getclobval()
     into out_xml
     from your_view where id = r.id;

     v_output := v_output || out_xml;
  end loop;
  v_output := v_output || '</logs>';
  dbms_output.put_line (v_output);
end;
/

<logs><log><ID>123456</ID><NAME>TEST</NAME></log><log><ID>1234567</ID><NAME>TEST1</NAME></log></logs>


PL/SQL procedure successfully completed.

Но проще избежать цикла курсора и просто присоединиться один раз:

declare
  in_xml clob := '<logs><log><ID>123456</ID></log><log><ID>1234567</ID></log></logs>';
  v_output clob;
begin
  select xmlelement("logs", xmlagg(xmlelement("log", xmlforest(v.id, v.name)))).getclobval()
  into v_output
  from xmltable(
    '/logs/log'
    passing xmltype(in_xml)
    columns id number path 'ID'
  ) x
  join your_view v on v.id = x.id;

  dbms_output.put_line (v_output);
end;
/

<logs><log><ID>123456</ID><NAME>TEST</NAME></log><log><ID>1234567</ID><NAME>TEST1</NAME></log></logs>


PL/SQL procedure successfully completed.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...