2

使用 Oracle PLSQL,我已经生成了许多 XMLType 类型的 XML 片段。我将这些存储在 XMLTYPE 类型的 VARRAY 中。我可以成功地将这些单独打印到文件中。

我接下来要做的是将所有这些片段融合在一起并将它们包装在另一个根元素中以生成单个文档。从我读过的内容来看,如果我能得到一个 XMLSEQUENCETYPE,那么我可以将它传递给 XMLCONCAT(..),它应该返回所有片段的 XMLType 连接。在此之后,它只是使用 XMLELEMENT(..) 添加根元素的情况。但是,我很难找到从我的 VARRAY 的 XMLTYPE 生成 XMLSEQUENCETYPE 的方法。

有谁知道如何做到这一点,事实上我采取的方法是否是最好的?(如果有人好奇,我正在尝试创建一个基本的 dbunit 类型框架。这个脚本的目的是创建一个工具,该工具可用于将 XML 数据集输出到文件,然后将其加载到单元测试中)。

这是plsql脚本:


set serveroutput on;
CREATE OR REPLACE TYPE rowset_query_type AS OBJECT ( 
   table_name          VARCHAR2(100),
   query_string        VARCHAR2(1024)
);
/

DECLARE

  TYPE XML_Fragments_Type IS VARRAY(1000) OF XMLTYPE;
  TYPE Rowset_Query_List_Type is VARRAY(1000) OF rowset_query_type;

  outputDir                 VARCHAR(200)  :=  'ORACLE_FILE_DIR';
  outputFile                VARCHAR(200)  :=  'TestDataSet.xml';

  qryCtx                    DBMS_XMLGEN.ctxHandle;
  rowsetResultFragments     XML_Fragments_Type;
  rowsetQueries             Rowset_Query_List_Type;  
  xmlResult                 xmltype;  
  rowsetQueryElement        rowset_query_type; 

  output                     CLOB;
BEGIN

 dbms_output.put_line('Exporting dataset...');

 -- export files to data fixture 

 -- define fixtures
 rowsetQueries := Rowset_Query_List_Type();
 rowsetQueries.EXTEND(2);

 rowsetQueries := Rowset_Query_List_Type(
 rowset_query_type('person', 'select * from person'),
 rowset_query_type('address','select * from address'));

 rowsetResultFragments := XML_Fragments_Type();
 rowsetResultFragments.EXTEND(rowsetQueries.count);

 FOR i IN rowsetQueries.FIRST..rowsetQueries.LAST 
 LOOP

  rowsetQueryElement := rowsetQueries(i);  
  dbms_output.put_line('Extracting dataset for table: ' || rowsetQueryElement.table_name || ' using query: ''' || rowsetQueryElement.query_string || '''');


  qryCtx := dbms_xmlgen.newContext(rowsetQueryElement.query_string);

  -- wrap the result up with a metadata tag containing the fixture tablename
  select xmlelement(
          "ROWSET_QUERY",
          xmlattributes(rowsetQueryElement.table_name as "tableName"),
              DBMS_XMLGEN.getXMLType(qryCtx)  
      )
  into rowsetResultFragments(i)
  from dual;

  --close context
  DBMS_XMLGEN.closeContext(qryCtx);

  -- print the results to console
  -- serialize the result for printing to output
  SELECT XMLSERIALIZE(
    CONTENT 
      rowsetResultFragments(i) 
    AS CLOB)
  INTO output
  FROM DUAL;

  DBMS_OUTPUT.PUT_LINE(output);

 END LOOP;




 -- concatenate the set of rowsetQueries result fragments to a single result clob
 --  ???

END;
/
4

2 回答 2

3

您快到了。

首先,将您的类型更改为 SQL 类型:

create or replace TYPE XML_Fragments_Type IS VARRAY(1000) OF XMLTYPE;
/

然后这样做

-- concatenate the set of rowsetQueries result fragments to a single result clob
 --  ???

 select xmlelement("root" ,xmlagg(column_value))
   into xmlresult
   from table(rowsetResultFragments);

例如:

    SQL> create or replace TYPE XML_Fragments_Type IS VARRAY(1000) OF XMLTYPE;
      2  /

    Type created.

    SQL> DECLARE
      2
      3    --TYPE XML_Fragments_Type IS VARRAY(1000) OF XMLTYPE;
      4    TYPE Rowset_Query_List_Type is VARRAY(1000) OF rowset_query_type;
      5
      6    outputDir                 VARCHAR(200)  :=  'ORACLE_FILE_DIR';
      7    outputFile                VARCHAR(200)  :=  'TestDataSet.xml';
      8
...
     26   rowsetQueries := Rowset_Query_List_Type(
     27   rowset_query_type('person', 'select table_name, owner from dba_tables where rownum = 1'),
     28   rowset_query_type('address','select owner, type_name, attributes from dba_types where rownum = 1'));
     29
...
     56
     57   select xmlelement("root" ,xmlagg(column_value))
     58     into xmlresult
     59     from table(rowsetResultFragments);
     60    SELECT XMLSERIALIZE(
     61      CONTENT
     62        xmlresult
     63      AS CLOB )
     64    INTO output
     65    FROM DUAL;
     66    DBMS_OUTPUT.PUT_LINE(output);
     67
     68
     69  END;
     70  /
    Exporting dataset...
    Extracting dataset for table: person using query: 'select table_name, owner from dba_tables where rownum = 1'
    Extracting dataset for table: address using query: 'select owner, type_name, attributes from dba_types where rownum = 1'
    <root>
      <ROWSET_QUERY tableName="person">
        <ROWSET>
          <ROW>
            <TABLE_NAME>ICOL$</TABLE_NAME>
            <OWNER>SYS</OWNER>
          </ROW>
        </ROWSET>
      </ROWSET_QUERY>
      <ROWSET_QUERY tableName="address">
        <ROWSET>
          <ROW>
            <OWNER>CTXSYS</OWNER>
            <TYPE_NAME>CATINDEXMETHODS</TYPE_NAME>
            <ATTRIBUTES>3</ATTRIBUTES>
          </ROW>
        </ROWSET>
      </ROWSET_QUERY>
    </root>
于 2013-02-13T10:28:15.090 回答
2

如果您不使用这些片段,则可以在循环中使用XMLCONCAT,然后在最后使用XMLELEMENT

SQL> DECLARE
  2     TYPE Rowset_Query_List_Type IS VARRAY(1000) OF rowset_query_type;
  3  
  4     outputDir  VARCHAR(200) := 'ORACLE_FILE_DIR';
  5     outputFile VARCHAR(200) := 'TestDataSet.xml';
  6  
  7     qryCtx             DBMS_XMLGEN.ctxHandle;
  8     rowsetQueries      Rowset_Query_List_Type;
  9     xmlResult          XMLTYPE;
 10     rowsetQueryElement rowset_query_type;
 11  BEGIN
 12     -- define fixtures
 13     rowsetQueries := Rowset_Query_List_Type(
 14                         rowset_query_type('person', 'select * from dual'),
 15                         rowset_query_type('address', 'select * from dual'));
 16  
 17     FOR i IN rowsetQueries.FIRST .. rowsetQueries.LAST LOOP
 18  
 19        rowsetQueryElement := rowsetQueries(i);
 20        dbms_output.put_line('Extracting dataset for table: '
 21                             || rowsetQueryElement.table_name
 22                             || ' using query: '''
 23                             || rowsetQueryElement.query_string || '''');
 24  
 25        qryCtx := dbms_xmlgen.newContext(rowsetQueryElement.query_string);
 26  
 27        -- concatenate
 28        SELECT xmlconcat(xmlResult,
 29                         xmlelement(
 30                            "ROWSET_QUERY",
 31                            xmlattributes(
 32                               rowsetQueryElement.table_name AS "tableName"),
 33                            DBMS_XMLGEN.getXMLType(qryCtx)))
 34          INTO xmlResult
 35          FROM dual;
 36  
 37        --close context
 38        DBMS_XMLGEN.closeContext(qryCtx);
 39  
 40     END LOOP;
 41  
 42     -- root element
 43     SELECT xmlelement(ROOT, xmlresult) INTO xmlresult FROM dual;
 44  
 45     dbms_output.put_line('result:');
 46     DBMS_OUTPUT.PUT_LINE(xmlResult.getClobVal());
 47  
 48  END;
 49  /

Extracting dataset for table: person using query: 'select * from dual'
Extracting dataset for table: address using query: 'select * from dual'
result:
<ROOT><ROWSET_QUERY tableName="person"><ROWSET>
  <ROW>
    <DUMMY>X</DUMMY>
  </ROW>
</ROWSET>
</ROWSET_QUERY><ROWSET_QUERY tableName="address"><ROWSET>
  <ROW>
    <DUMMY>X</DUMMY>
  </ROW>
</ROWSET>
</ROWSET_QUERY></ROOT>

PL/SQL procedure successfully completed
于 2013-02-13T10:40:49.987 回答