从oracle表生成XML

时间:2014-02-21 07:27:13

标签: xml oracle11g plsqldeveloper

需要创建一个通用存储过程,该过程将表名作为输入参数并使用以下格式创建xml文件。 Xml文件名应为表名。

    <XML>
    <TABLENAME></TABLENAME>
    <RECORDS>
    <RECORD>
              <COLNAME>AAA</COLNAME>
              <COLNAME>AAA</COLNAME>
    <RECORD>
    <RECORD>
              <COLNAME>AAA</COLNAME>
              <COLNAME>AAA</COLNAME>
    <RECORD>
    <RECORD>
              <COLNAME>AAA</COLNAME>
              <COLNAME>AAA</COLNAME>
    <RECORD>
    <RECORD>
              <COLNAME>AAA</COLNAME>
              <COLNAME>AAA</COLNAME>
    <RECORD>
    <RECORD>
              <COLNAME>AAA</COLNAME>
              <COLNAME>AAA</COLNAME>
    <RECORD>
    </RECORDS>
    </XML> 


<TABLENAME>  = actual table name(case should be same as in database)
<COLNAME> = actual column names from table(case should be same as in database)
Keep other tags as it is. Repeat <RECORD> tag for each row retrieved.

1 个答案:

答案 0 :(得分:2)

Oracle有一个内置函数来将表的内容作为XML获取:

create table t42(id number, str varchar2(10));
insert into t42 values (1, 'AA');
insert into t42 values (2, 'BB');

select dbms_xmlgen.getxmltype('select * from t42')
from dual;

DBMS_XMLGEN.GETXMLTYPE('SELECT*FROMT42')
----------------------------------------
<ROWSET>
 <ROW>
  <ID>1</ID>
  <STR>AA</STR>
 </ROW>
 <ROW>
  <ID>2</ID>
  <STR>BB</STR>
 </ROW>
</ROWSET>

您可以在其周围添加自己的标签;可以作为查询完成,但因为你想要一个存储过程:

create or replace function table_to_xml(table_name in varchar2) return xmltype as
  xml xmltype;
begin
  select xmlelement("XML",
      xmlelement(evalname(table_name),
        dbms_xmlgen.getxmltype('select * from "' || table_name || '"')))
  into xml
  from dual;

  return xml;
end table_to_xml;
/

select table_to_xml('T42') from dual;

TABLE_TO_XML('T42')
----------------------------------------
<XML><T42><ROWSET>
  <ROW>
    <ID>1</ID>
    <STR>AA</STR>
  </ROW>
  <ROW>
    <ID>2</ID>
    <STR>BB</STR>
  </ROW>
</ROWSET>
</T42></XML>

所以这有你想要的结构(好吧,我想,但见下文),但有ROWSETROW而不是RECORDSRECORD可能无关紧要,这取决于您是否仍在为此接口开发格式。如果它确实重要,那么您可以应用更进一步的步骤to rename those nodes,或者 - 更有帮助 - 使用dbms_xmlgen程序setrowsettagsetrowtag,这在您的程序中很简单(和如下所示。

我假设您显示的内容为<TABLENAME></TABLENAME>是一个错误,并且您想要该标记内的记录。如果没有,并且您确实希望由于某种原因,将函数中的查询更改为:

  select xmlelement("XML",
      xmlconcat(xmlelement(evalname(table_name), null),
      dbms_xmlgen.getxmltype('select * from "' || table_name || '"')))
  into xml
  from dual;

然后,您可以按照通常的方式将其写入文件;如果您正在从SQL * Plus等进行调用,则可以选择并假脱机,或者如果您根本不想让它返回,您可以添加UTL_FILE指令从过程中写入文件,但这样做会有成为数据库服务器上的目录对象,这可能不方便。

主要是为了我自己的利益,因为我没有用XML做很多事情:

create or replace procedure table_to_xml_file(table_name in varchar2) as
  ctx dbms_xmlgen.ctxhandle;
  clb clob;
  file utl_file.file_type;
  buffer varchar2(32767);
  position pls_integer := 1;
  chars pls_integer := 32767;
begin
  ctx := dbms_xmlgen.newcontext('select * from "' || table_name || '"');
  dbms_xmlgen.setrowsettag(ctx, 'RECORDS');
  dbms_xmlgen.setrowtag(ctx, 'RECORD');

  select xmlserialize(document
        xmlelement("XML",
          xmlelement(evalname(table_name),
            dbms_xmlgen.getxmltype(ctx)))
      indent size = 2)
  into clb
  from dual;

  dbms_xmlgen.closecontext(ctx);

  file := utl_file.fopen('<directory>', table_name || '.xml', 'w', 32767);
  while position < dbms_lob.getlength(clb) loop
    dbms_lob.read(clb, chars, position, buffer);
    utl_file.put(file, buffer);
    utl_file.fflush(file);
    position := position + chars;
  end loop;
  utl_file.fclose(file);
end table_to_xml_file;
/

使用exec table_to_xml_file('T42')运行时,会在T42.xml目录对象指向的服务器目录中生成一个名为<directory>的文件,其中包含:

<XML>
  <T42>
    <RECORDS>
      <RECORD>
        <ID>1</ID>
        <STR>AA</STR>
      </RECORD>
      <RECORD>
        <ID>2</ID>
        <STR>BB</STR>
      </RECORD>
    </RECORDS>
  </T42>
</XML>

顺便说一句,我在dbms_xmlgen.getxmltype调用中的select中围绕表名放了双引号。这是为了满足表名的“案例应与数据库中的相同”要求;必须在正确的情况下传递给程序,否则会出错。这比尝试以某种方式纠正过程中的情况更简单,如果你有两个除了案例之外具有相同名称的表,这将是尴尬或不可能的。无论如何,列名称都将在正确的情况下。