Oracle有一個包XMLDOM,可以很方便的建立XML檔案.舉個簡單的例子.產生Test.xml,內容如下
<staff content = "name and id">
<member >
<name>Arwen</name>
<eno>123</eno>
</member>
<member >
<name>Tom</name>
<eno>456</eno>
</member>
</staff>
---------------------------------------------------------------------------------------------------------------------------------------
--產生xml的代碼
declare
doc XMLDOM.DOMDOCUMENT;
doc_node XMLDOM.DOMNODE;
root_node XMLDOM.DOMNODE;
user_node XMLDOM.DOMNODE;
item_node XMLDOM.DOMNODE;
root_elmt XMLDOM.DOMELEMENT;
user_elmt XMLDOM.DOMELEMENT;
item_elmt XMLDOM.DOMELEMENT;
item_text XMLDOM.DOMTEXT;
begin
doc := XMLDOM.NEWDOMDOCUMENT;
xmldom.setVersion(doc, '1.0');
xmldom.setCharset(doc, 'UTF-8');
--根節點
doc_node := XMLDOM.MAKENODE(doc);
root_elmt := XMLDOM.CREATEELEMENT(doc,'staff');
XMLDOM.SETATTRIBUTE(root_elmt,'content ','name and id');
root_node:=XMLDOM.APPENDCHILD(doc_node, XMLDOM.MAKENODE(root_elmt));
--節點1
user_elmt := XMLDOM.CREATEELEMENT(doc,'member');
user_node :=XMLDOM.APPENDCHILD(root_node, XMLDOM.MAKENODE(user_elmt));
item_elmt :=XMLDOM.CREATEELEMENT(doc,'name');
item_node :=XMLDOM.APPENDCHILD(user_node, XMLDOM.MAKENODE(item_elmt));
item_text := XMLDOM.CREATETEXTNODE(doc,'Arwen');
item_node:=XMLDOM.APPENDCHILD(item_node, XMLDOM.MAKENODE(item_text));
item_elmt :=XMLDOM.CREATEELEMENT(doc,'eno');
item_node :=XMLDOM.APPENDCHILD(user_node, XMLDOM.MAKENODE(item_elmt));
item_text := XMLDOM.CREATETEXTNODE(doc,'123');
item_node:=XMLDOM.APPENDCHILD(item_node, XMLDOM.MAKENODE(item_text));
--節點2
user_elmt := XMLDOM.CREATEELEMENT(doc,'member');
user_node :=XMLDOM.APPENDCHILD(root_node, XMLDOM.MAKENODE(user_elmt));
item_elmt :=XMLDOM.CREATEELEMENT(doc,'name');
item_node :=XMLDOM.APPENDCHILD(user_node, XMLDOM.MAKENODE(item_elmt));
item_text := XMLDOM.CREATETEXTNODE(doc,'tom');
item_node:=XMLDOM.APPENDCHILD(item_node, XMLDOM.MAKENODE(item_text));
item_elmt :=XMLDOM.CREATEELEMENT(doc,'eno');
item_node :=XMLDOM.APPENDCHILD(user_node, XMLDOM.MAKENODE(item_elmt));
item_text := XMLDOM.CREATETEXTNODE(doc,'456');
item_node:=XMLDOM.APPENDCHILD(item_node, XMLDOM.MAKENODE(item_text));
--寫入作業系統檔案中
XMLDOM.WRITETOFILE(doc,'DIR'||'\Test.xml');--注意必須先建立一個檔案目錄dir
--可以通過語句 : create or replace directory dir as 'd:\temp'
XMLDOM.FREEDOCUMENT(doc);
end;
這樣產生XML檔案非常方便,能滿足一般的應用了.但是XMLDOM有個缺點,就是一次性在記憶體中產生所有xml檔案內容,然後寫入到磁碟檔案中.如果xml檔案太大,比如說有個table有幾個G,想把它儲存成xml檔案.這樣可能就會出現記憶體不足,組建檔案失敗.那該咋整呢?
1.可能首先想到的是用UTL_FILE去組建檔案.
裡面的內容全部手動寫成xml格式的,然後儲存成xml尾碼的檔案.這樣確實可行.但有個麻煩問題時如果一些節點內容含有xml的五個保留字元的話(&,<,>,'," 分別是和號,小於符號,大於符號,單引號,雙引號),我們如果以文本方式開啟xml檔案是看不到節點內容裡面有這些保留字的,都轉換成了對應的&, >, <, &apos, ".節點指定的是上面的Arwen或123,假如有名字(A&r<w>e'n")則儲存到xml檔案中應該改成(A&r>w<e&aposn").如果用xmldom會預設去轉換,不用我們管了.如果用UTL_FILE必須手動寫代碼去轉換.
2.結合使用XMLDOM和utl_file
假如有表staff(name varchar2(30), eno integer),裡面有幾個G的內容,要轉換成開頭講的那種格式的xml檔案
--產生xml的代碼其中XML檔案的頭和尾用UTL_FILE直接寫入檔案中,節點內容用xmldom產生,然後寫到clob變數中,再把clob變數值用utl_file寫入到xml檔案中
declare
STAFFINFO UTL_FILE.FILE_TYPE;
v_temp clob;
cursor c_table_info is
select name,eno from staff;
v_name varchar2(30);
v_eno integer;
doc XMLDOM.DOMDOCUMENT;
doc_node XMLDOM.DOMNODE;
root_node XMLDOM.DOMNODE;
user_node XMLDOM.DOMNODE;
item_node XMLDOM.DOMNODE;
root_elmt XMLDOM.DOMELEMENT;
user_elmt XMLDOM.DOMELEMENT;
item_elmt XMLDOM.DOMELEMENT;
item_text XMLDOM.DOMTEXT;
begin
--xml header
STAFFINFO :=utl_file.fopen_nchar('DIR','Test.xml','W',32767);--跟前面說的一樣必須先建立一個directory才行
UTL_FILE.PUT_LINE_NCHAR(STAFFINFO
,'<staff content = "name and id">');
UTL_FILE.FFLUSH(STAFFINFO );--直接寫入到磁碟檔案中,不會停留在記憶體中
UTL_FILE.FCLOSE(STAFFINFO );
open c_table_info;
loop
fetch c_table_info into v_name,v_eno;
exit when c_table_info%notfound;
--XML節點
doc := XMLDOM.NEWDOMDOCUMENT;
xmldom.setCharset(doc, 'UTF-8');
doc_node := XMLDOM.MAKENODE(doc);
user_elmt := XMLDOM.CREATEELEMENT(doc,'member');
user_node :=XMLDOM.APPENDCHILD(doc_node, XMLDOM.MAKENODE(user_elmt));
item_elmt :=XMLDOM.CREATEELEMENT(doc,'name');
item_node :=XMLDOM.APPENDCHILD(user_node, XMLDOM.MAKENODE(item_elmt));
item_text := XMLDOM.CREATETEXTNODE(doc,v_name);
item_node:=XMLDOM.APPENDCHILD(item_node, XMLDOM.MAKENODE(item_text));
item_elmt :=XMLDOM.CREATEELEMENT(doc,'eno');
item_node :=XMLDOM.APPENDCHILD(user_node, XMLDOM.MAKENODE(item_elmt));
item_text := XMLDOM.CREATETEXTNODE(doc,'eno');
item_node:=XMLDOM.APPENDCHILD(item_node, XMLDOM.MAKENODE(item_text));
v_temp :=' ';
--寫入到臨時變數v_temp中
XMLDOM.WRITETOCLOB(doc,v_temp);
STAFFINFO :=utl_file.fopen_nchar('DIR','Test.xml','A',32767);--以a模式會在檔案後新增內容,用w會覆蓋之前的內容
UTL_FILE.PUT_LINE_NCHAR(STAFFINFO
,v_temp);
UTL_FILE.FFLUSH(STAFFINFO );
UTL_FILE.FCLOSE(STAFFINFO );
XMLDOM.FREEDOCUMENT(doc);
end loop;
close c_table_info;
--xml tail
STAFFINFO :=utl_file.fopen_nchar('DIR','Test.xml','a',32767);
UTL_FILE.PUT_LINE_NCHAR(STAFFINFO
,'</staff>');
UTL_FILE.FFLUSH(STAFFINFO );
UTL_FILE.FCLOSE(STAFFINFO );
end;