问题
XML
<logs>
<log>
<ID>123456</ID>
<NAME>TEST</NAME>
</log>
</logs>
<logs>
<log>
<ID>1234567</ID>
<NAME>TEST1</NAME>
</log>
</logs>
上面的xml日志中的即将在log标记后关闭。
但是我需要XML,其中日志标记在下面的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;
谁能建议我如何使用xmlelement解决多个xml元素。
输入是XML,解析xml输出后应该是xml。
如果我需要Dyanamic XML,可以在下面使用代码。
select xmltype(cursor(select * from view )) from dual;
光标在循环中。
任何建议都是最欢迎的。
答案 0 :(得分:3)
如果我了解您要做什么,那么您是从XML文档的字符串版本开始的,例如:
<logs><log><ID>123456</ID></log><log><ID>1234567</ID></log></logs>
,并尝试添加与从视图中获得的每个name
值相对应的id
值。
您可以使用XMLTable提取所有ID,将其加入视图,然后通过XMLAgg重建最终的XML,例如:
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>
如果您确实想使用链接到的问题中显示的机制,则可以通过将循环内生成的每个元素附加到循环的外部,并在其外部添加开始和结束logs
标记,来构建最终输出CLOB。循环:
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.