Oracle包XMLDOM创建XML文件及其缺点

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文件是看不到节点内容里面有这些保留字的,都转换成了对应的&amp, &gt, &lt, &apos, &quot.节点指定的是上面的Arwen或123,假如有名字(A&r<w>e'n")则保存到xml文件中应该改成(A&ampr&gtw&lte&aposn&quot).如果用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;

 

 

 

你可能感兴趣的:(oracle,xml,user,table,Integer)