使用 PL/SQL 创建 XML
Posted
技术标签:
【中文标题】使用 PL/SQL 创建 XML【英文标题】:Creating XML with PL/SQL 【发布时间】:2017-01-13 23:16:49 【问题描述】:我需要用 PL/SQL 创建 XML,我的解决方案中有两个问题。
示例代码如下所示:
select xmlelement(
"tag_one",
XMLAGG(
xmlelement("user",
xmlforest(
'something' "two"
, 'else' "tree"
, NULL "four"
, (
select sys_xmlagg(
xmlelement(
"secondGoup",
xmlforest(
'true' "five"
, 123 "six"
)
)
)
FROM dual
) "group_tag"
)
)
)
) as "XML_QUERY"
FROM dual
我得到的 XML 看起来像这样
<tag_one>
<user>
<two>something</two>
<tree>else</tree>
<group_tag>
<ROWSET>
<secondGoup>
<five>true</five>
<six>123</six>
</secondGoup>
</ROWSET>
</group_tag>
</user>
</tag_one>
它的问题是:
1.) 我不需要 ROWSET 标签,也不知道如何删除它
2.) 我的 XML 中需要空标记 4
<four></four>
我应该提到可以有多个 secondGoup 标签,但是这段代码可以毫无问题地生成它们
注意以防万一您有更好的方法来创建此 XML
<tag_one>
<user>
<two>something</two>
<tree>else</tree>
<four></four>
<group_tag>
<secondGoup>
<five>true</five>
<six>123</six>
</secondGoup>
<secondGoup>
<five>true</five>
<six>456</six>
</secondGoup>
<secondGoup>
<five>false</five>
<six>789</six>
</secondGoup>
</group_tag>
</user>
</tag_one>
5 和 6 的查询如下所示
SELECT t1.field1 "five"
, t2.field2 "six"
FROM table1 t1
JOIN table2 t2 ON t1.field4 = t2.field2
WHERE t2.field3 = 3
这会返回 X 行(有时返回 1,有时返回 2、3、20,...)。在WHERE中添加3作为例子,实际查询中存在变量值
【问题讨论】:
【参考方案1】:你好,你的意思是得到这个输出:
<tag_one>
<user>
<two>something</two>
<tree>else</tree>
<four></four>
<group_tag>
<secondGoup>
<five>true</five>
<six>123</six>
</secondGoup>
<secondGoup>
<five>true</five>
<six>456</six>
</secondGoup>
<secondGoup>
<five>true</five>
<six>789</six>
</secondGoup>
</group_tag>
</user>
</tag_one>
这是正确的查询:
SELECT XMLELEMENT (
"tag_one",
XMLAGG (
XMLELEMENT (
"user",
XMLFOREST (
'something' "two",
'else' "tree",
'' "four",
XMLFOREST (
XMLFOREST ('true' "five", 123 "six") "secondGoup",
XMLFOREST ('true' "five", 456 "six") "secondGoup",
XMLFOREST ('true' "five", 789 "six") "secondGoup") "group_tag"))))
AS "XML_QUERY"
FROM DUAL
===========编辑==================
您好,再次,对于您的动态查询,我们不再可以使用 XMLELEMT 和相关函数,因为它们将返回 clob,使用它们会很麻烦,我在这里为您找到了一个很长的 pl/sql 块(它是太大太复杂了,但我让它适用于你的情况):
DECLARE
L_XMLTYPE XMLTYPE;
L_DOMDOC DBMS_XMLDOM.DOMDOCUMENT;
L_ROOT_NODE DBMS_XMLDOM.DOMNODE;
L_SUPP_NUM_ELEMENT DBMS_XMLDOM.DOMELEMENT;
L_SUPP_NAME_ELEMENT DBMS_XMLDOM.DOMELEMENT;
L_SUPP_NUM_NODE DBMS_XMLDOM.DOMNODE;
L_SUPP_NAME_NODE DBMS_XMLDOM.DOMNODE;
L_SUPP_NUM_TNODE DBMS_XMLDOM.DOMNODE;
L_SUPP_NAME_TNODE DBMS_XMLDOM.DOMNODE;
L_SUPP_NUM_TEXT DBMS_XMLDOM.DOMTEXT;
L_SUPP_NAME_TEXT DBMS_XMLDOM.DOMTEXT;
L_C1 DBMS_XMLDOM.DOMELEMENT;
L_C1_NODE DBMS_XMLDOM.DOMNODE;
L_C2 DBMS_XMLDOM.DOMELEMENT;
L_C2_NODE DBMS_XMLDOM.DOMNODE;
L_C2_TEXT DBMS_XMLDOM.DOMTEXT;
L_C2_TEXT_NODE DBMS_XMLDOM.DOMNODE;
L_SUPPLIER_ELEMENT DBMS_XMLDOM.DOMELEMENT;
L_SUPPLIER_NODE DBMS_XMLDOM.DOMNODE;
L_SUP_NODE DBMS_XMLDOM.DOMNODE;
BEGIN
-- Create an empty XML document
L_DOMDOC := DBMS_XMLDOM.NEWDOMDOCUMENT;
-- Create a root node
L_ROOT_NODE := DBMS_XMLDOM.MAKENODE (L_DOMDOC);
-- Create a new Supplier Node and add it to the root node
L_SUP_NODE :=
DBMS_XMLDOM.APPENDCHILD (
L_ROOT_NODE,
DBMS_XMLDOM.MAKENODE (
DBMS_XMLDOM.CREATEELEMENT (L_DOMDOC, 'tag_one')));
L_C1 := DBMS_XMLDOM.CREATEELEMENT (L_DOMDOC, 'user');
L_C1_NODE :=
DBMS_XMLDOM.APPENDCHILD (L_SUP_NODE, DBMS_XMLDOM.MAKENODE (L_C1));
L_C2 := DBMS_XMLDOM.CREATEELEMENT (L_DOMDOC, 'two');
L_C2_NODE :=
DBMS_XMLDOM.APPENDCHILD (L_C1_NODE, DBMS_XMLDOM.MAKENODE (L_C2));
L_C2_TEXT := DBMS_XMLDOM.CREATETEXTNODE (L_DOMDOC, 'something');
L_C2_TEXT_NODE :=
DBMS_XMLDOM.APPENDCHILD (L_C2_NODE, DBMS_XMLDOM.MAKENODE (L_C2_TEXT));
L_C2 := DBMS_XMLDOM.CREATEELEMENT (L_DOMDOC, 'three');
L_C2_NODE :=
DBMS_XMLDOM.APPENDCHILD (L_C1_NODE, DBMS_XMLDOM.MAKENODE (L_C2));
L_C2_TEXT := DBMS_XMLDOM.CREATETEXTNODE (L_DOMDOC, 'else');
L_C2_TEXT_NODE :=
DBMS_XMLDOM.APPENDCHILD (L_C2_NODE, DBMS_XMLDOM.MAKENODE (L_C2_TEXT));
L_C2 := DBMS_XMLDOM.CREATEELEMENT (L_DOMDOC, 'group_tag');
L_C2_NODE :=
DBMS_XMLDOM.APPENDCHILD (L_C1_NODE, DBMS_XMLDOM.MAKENODE (L_C2));
FOR SUP_REC IN (SELECT T1.FIELD1, T2.FIELD2
FROM TABLE1 T1 JOIN TABLE2 T2 ON T1.FIELD4 = T2.FIELD2
WHERE T2.FIELD3 = 3)
LOOP
-- For each record, create a new Supplier element
-- and add this new Supplier element to the Supplier Parent node
L_SUPPLIER_ELEMENT := DBMS_XMLDOM.CREATEELEMENT (L_DOMDOC, 'secondGoup');
L_SUPPLIER_NODE :=
DBMS_XMLDOM.APPENDCHILD (
L_C2_NODE,
DBMS_XMLDOM.MAKENODE (L_SUPPLIER_ELEMENT)
);
-- Each Supplier node will get a Number node which contains the Supplier Number as text
L_SUPP_NUM_ELEMENT := DBMS_XMLDOM.CREATEELEMENT (L_DOMDOC, 'five');
L_SUPP_NUM_NODE :=
DBMS_XMLDOM.APPENDCHILD (
L_SUPPLIER_NODE,
DBMS_XMLDOM.MAKENODE (L_SUPP_NUM_ELEMENT)
);
L_SUPP_NUM_TEXT := DBMS_XMLDOM.CREATETEXTNODE (L_DOMDOC, SUP_REC.FIELD1);
L_SUPP_NUM_TNODE :=
DBMS_XMLDOM.APPENDCHILD (
L_SUPP_NUM_NODE,
DBMS_XMLDOM.MAKENODE (L_SUPP_NUM_TEXT)
);
-- Each Supplier node will get a Name node which contains the Supplier Name as text
L_SUPP_NAME_ELEMENT := DBMS_XMLDOM.CREATEELEMENT (L_DOMDOC, 'six');
L_SUPP_NAME_NODE :=
DBMS_XMLDOM.APPENDCHILD (
L_SUPPLIER_NODE,
DBMS_XMLDOM.MAKENODE (L_SUPP_NAME_ELEMENT)
);
L_SUPP_NAME_TEXT :=
DBMS_XMLDOM.CREATETEXTNODE (L_DOMDOC, SUP_REC.FIELD2);
L_SUPP_NAME_TNODE :=
DBMS_XMLDOM.APPENDCHILD (
L_SUPP_NAME_NODE,
DBMS_XMLDOM.MAKENODE (L_SUPP_NAME_TEXT)
);
END LOOP;
L_XMLTYPE := DBMS_XMLDOM.GETXMLTYPE (L_DOMDOC);
DBMS_XMLDOM.FREEDOCUMENT (L_DOMDOC);
DBMS_OUTPUT.PUT_LINE (L_XMLTYPE.GETCLOBVAL);
END;
输出:
<tag_one>
<user>
<two>something</two>
<three>else</three>
<group_tag>
<secondGoup>
<five>123</five>
<six>014</six>
</secondGoup>
<secondGoup>
<five>456</five>
<six>011</six>
</secondGoup>
<secondGoup>
<five>789</five>
<six>011</six>
</secondGoup>
<secondGoup>
<five>012</five>
<six>011</six>
</secondGoup>
<secondGoup>
<five>345</five>
<six>011</six>
</secondGoup>
<secondGoup>
<five>678</five>
<six>011</six>
</secondGoup>
<secondGoup>
<five>901</five>
<six>011</six>
</secondGoup>
<secondGoup>
<five>234</five>
<six>011</six>
</secondGoup>
<secondGoup>
<five>567</five>
<six>011</six>
</secondGoup>
</group_tag>
</user>
</tag_one>
【讨论】:
请注意不要通过NULL来创建空标签,可以使用NVL()函数来转换可能的NULL 随心所欲。 漂亮,没有行集标签,喜欢它:) 只是一件事,应该用单独的查询提取 5 和 6 的值(并且它们有不同的行数),不知道我该怎么做这里。在原帖中添加示例 @BeRightBack 您能否添加一个包含五个和六个值的示例查询? 我使用了这个链接中的代码:quest4apps.com/create-xml-using-dbms_xmldom 太棒了!!!刚刚使用 dbms_xmldom 编写,就像魅力一样,谢谢。顺便说一句,它一点也不复杂,它很简单,只是看起来很大,但这不是问题以上是关于使用 PL/SQL 创建 XML的主要内容,如果未能解决你的问题,请参考以下文章