2013-02-13 1 views
3

Oracle PLSQL을 사용하여 XMLType 유형의 여러 XML 조각을 생성 한 지점에 도달했습니다. 나는 이것들을 XMLTYPE 타입의 VARRAY에 저장했다. 이 파일을 개별적으로 파일에 성공적으로 인쇄 할 수 있습니다.XML 형식의 VARAY를 연결하는 좋은 방법은 무엇입니까

다음에 내가하고 싶은 것은 이러한 모든 조각들을 함께 융합시켜 하나의 문서를 생성하기 위해 다른 루트 요소로 감싸는 것입니다. 내가 XMLSEQUENCETYPE을 잡을 수 있다면 읽은 것부터 XMLCONCAT (..)로 넘겨 줄 수 있으며 모든 파편의 XMLType 연결을 반환해야합니다. 이 후 XMLELEMENT (..)를 사용하여 루트 요소를 추가하는 경우 일 수 있습니다. 그러나 XMLTYPE의 VARRAY에서 XMLSEQUENCETYPE을 생성하는 방법을 찾는 데 어려움이 있습니다.

이 작업을 수행하는 방법을 알고 있으며 사실 내가 취한 접근 방식이 최선인지 여부를 아는 사람이 있습니까? (누군가 궁금하다면 기본 dbunit 형식의 프레임 워크를 만들려고합니다.이 스크립트의 목적은 XML 데이터 집합을 파일로 출력하는 데 사용할 수있는 도구를 만드는 것입니다. 나중에이 파일을 단위 테스트에로드합니다.


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; 
/

답변

3

당신은 거의 다 :

다음은 PLSQL 스크립트입니다.

첫째, 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> 
+0

감사합니다. – Ellis

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 
+1

+1 고마워,이 솔루션도 잘 작동하고 실제로 달성하기 위해 노력하고있어보다 우아한 접근 방식처럼 보입니다. XMLTypes의 배열을 연결하는 문제에 대한 더 가까운 해결책이기 때문에 첫 번째 대답을 대답으로 받아 들일 것입니다. – Ellis

+0

@ellis 동의, DazzaL의 솔루션은 당신이 찾고 있던 것과 정확히 같습니다 =) –

관련 문제