在oracle中对结果集执行子查询以创建XML

时间:2017-05-05 07:50:51

标签: sql xml oracle xml-parsing

我在Oracle中从数据库返回了以下类型的结果集:

**Name    Type  SubName        Number**
test    B     tim            1
test    B     jfd            2
testV   I     rr             1
testV   I     sim            2
dsgsg   B     sgsg           1
dsgsg   B     sfsfssfsffs    2

我想要的是使用SQL来操作此结果来创建此类型的XML

<NameList>
<Name/>
<Type/>
<SubNameList>
<SubName>
<Name/>
<Number/>
</SubName>
</SubNameList>
</NameList>

例如:对于结果集的前两个记录具有相同的名称,因此XML将为:

<NameList>
<Name>test</Name>
<Type>B</Type>
<SubNameList>
<SubName>
<Name>tim</Name>
<Number>1</Number>
</SubName>
<SubName>
<Name>jfd</Name>
<Number>2</Number>
</SubName>
</SubNameList>
</NameList>

到目前为止我做了什么: 我有两张桌子:

TABLE1
    **ID NAME  KEY**
      1  test  101
      1  testV 102
      1  dsgsg 103

TABLE2   
    **ID SUBNAME TYPE NUMBER KEY**
      1  tim     B    1      101
      1  jfd     B    2      101
      1  rr      I    1      102
      1  sim     I    2      102
      1  sgsg    B    1      103
      1  sfsfssfsffs B 2     103

SQL:

Select A.NAME, B.TYPE, B.SUBNAME, B.NUMBER
FROM TABLE1 A INNER JOIN TABLE2 B
ON A.ID = B.ID WHERE A.ID = '1';

我在oracle中使用XMLELEMENT()创建了XML:

SET SERVEROUTPUT ON;
DECLARE NAME_XML XMLTYPE;
v_offset number := 1;
v_chunk_size number := 255;
BEGIN
Select XMLAGG(XMLELEMENT("NAMELIST",
XMLELEMENT("Name", A.NAME),
XMLELEMENT("Type", B.TYPE),
XMLELEMENT("SubName", B.SUBNAME),
XMLELEMENT("Number", B.NUMBER)))
INTO NAME_XML 
FROM TABLE1 A INNER JOIN TABLE2 B
ON A.ID = B.ID WHERE A.ID = '1';

loop
    exit when v_offset > dbms_lob.getlength(NAME_XML.getClobVal());
    dbms_output.put_line( dbms_lob.substr(NAME_XML.getClobVal(), 
    v_chunk_size, v_offset ) );
    v_offset := v_offset + v_chunk_size;
end loop; 
END;

正在创建此类型的XML:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <NAMELIST>
      <Name>test</Name>
      <Type>B</Type>
      <SubName>tim</SubName>
      <Number>1</Number>
   </NAMELIST>
.
.
.
.
.
   <NAMELIST>
      <Name>dsgsg</Name>
      <Type>B</Type>
      <SubName>sfsfssfsffs</SubName>
      <Number>2</Number>
   </NAMELIST>
</root>

如何实现此类型的XML格式:

<NameList>
<Name>test</Name>   
<Type>B</Type>
<SubNameList>
<SubName>
<Name>tim</Name>
<Number>1</Number>
</SubName>
<SubName>
<Name>jfd</Name>            
<Number>2</Number>
</SubName>
</SubNameList>
</NameList>
....
....
....
....

任何输入都会有所帮助。

1 个答案:

答案 0 :(得分:0)

您可以使用以下程序:

CREATE OR REPLACE PROCEDURE MakePrettyXml(xmlString IN OUT NOCOPY CLOB, intent IN VARCHAR2 DEFAULT 'yes') IS

    xmlDocFragment DBMS_XMLDOM.DOMDOCUMENTFRAGMENT;
    xslProc DBMS_XSLPROCESSOR.PROCESSOR;
    xsl DBMS_XSLPROCESSOR.STYLESHEET;
    xmlStringOut CLOB;

BEGIN

    DBMS_LOB.CREATETEMPORARY(xmlStringOut, TRUE);
    xslProc := DBMS_XSLPROCESSOR.NEWPROCESSOR; 
    xsl := DBMS_XSLPROCESSOR.NEWSTYLESHEET(
        '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">'||
            '<xsl:output method="xml" indent="'||intent||'"/>'||
            '<xsl:template match="@*|node( )">'||
                '<xsl:copy>'||
                    '<xsl:apply-templates select="@*|node( )"/>'||
                '</xsl:copy>'||
            '</xsl:template>'||
        '</xsl:stylesheet>', NULL);

    xmlDocFragment := DBMS_XSLPROCESSOR.PROCESSXSL(p => xslProc, ss => xsl, cl => xmlString);
    DBMS_XMLDOM.WRITETOCLOB(DBMS_XMLDOM.MAKENODE(xmlDocFragment), xmlStringOut);

    DBMS_XSLPROCESSOR.FREESTYLESHEET(xsl);
    DBMS_XSLPROCESSOR.FREEPROCESSOR(xslProc);

    xmlString := xmlStringOut; 
    DBMS_LOB.FREETEMPORARY(xmlStringOut);

END MakePrettyXml;

结果:

DECLARE
    xmlString CLOB := '<root><NAMELIST>
      <Name>test</Name><Type>B</Type><SubName>tim</SubName><Number>1</Number>
   </NAMELIST>
   <NAMELIST>
      <Name>dsgsg</Name>
      <Type>B</Type><SubName>sfsfssfsffs</SubName>
      <Number>2</Number>
   </NAMELIST>
</root>';

BEGIN

    MakePrettyXml(xmlString, 'no');
    DBMS_OUTPUT.PUT_LINE(xmlString);

    MakePrettyXml(xmlString);
    DBMS_OUTPUT.PUT_LINE(xmlString);

END;

<root>
<NAMELIST>
<Name>test</Name>
<Type>B</Type>
<SubName>tim</SubName>
<Number>1</Number>
</NAMELIST>
<NAMELIST>
<Name>dsgsg</Name>
<Type>B</Type>
<SubName>sfsfssfsffs</SubName>
<Number>2</Number>
</NAMELIST>
</root>

<root>
  <NAMELIST>
    <Name>test</Name>
    <Type>B</Type>
    <SubName>tim</SubName>
    <Number>1</Number>
  </NAMELIST>
  <NAMELIST>
    <Name>dsgsg</Name>
    <Type>B</Type>
    <SubName>sfsfssfsffs</SubName>
    <Number>2</Number>
  </NAMELIST>
</root>

<强>更新

我希望您的问题与XML内容有关,而不是格式。在这种情况下尝试(未测试)

Select XMLELEMENT("NameList", 
   XMLELEMENT("Name", A.NAME),
   XMLELEMENT("Type", B.TYPE),
   XMLELEMENT("SubNameList", 
     XMLAGG(XMLELEMENT("SubName", 
     XMLELEMENT("Name", B.NAME)
     XMLELEMENT("Number", B.NUMBER))))
   )
INTO NAME_XML 
FROM TABLE1 A INNER JOIN TABLE2 B
ON A.ID = B.ID WHERE A.ID = '1';