下面是一个从Oracle 11g数据库(我在这个简单示例中使用双表)中获取数据到平面文件的简单示例。
我希望文件中包含以下格式。
<message>
<production>
<prodCategoryType>test type 1</prodCategoryType>
<prodStatusType>prod status 1</prodStatusType>
</production>
</message>
<message>
<production>
<prodCategoryType>test type 2</prodCategoryType>
<prodStatusType>prod status 2</prodStatusType>
</production>
</message>
但是我得到了以下内容,这似乎是缺少启动消息和生产代码,并在中间放置一个奇怪的 on&gt; 。
<message>
<production>
<prodCategoryType>test type 1</prodCategoryType>
<prodStatusType>prod status 1</prodStatusType>
</production>
</message>
on>
<prodCategoryType>test type 2</prodCategoryType>
<prodStatusType>prod status 2</prodStatusType>
</production>
</message>
我做错了吗?
DECLARE
l_file UTL_FILE.FILE_TYPE;
l_clob CLOB;
l_buffer VARCHAR2(32767);
l_amount BINARY_INTEGER := 32767;
l_pos INTEGER := 1;
l_extract_dir CONSTANT dba_directories.directory_name%TYPE:= 'REPORTS_OUT_DIR'; -- \\data2\data\download\d7prdv1\prsrepreports
l_xmltype XMLTYPE;
l_domdoc dbms_xmldom.DOMDocument;
l_root_node dbms_xmldom.DOMNode;
l_message_node dbms_xmldom.DOMNode;
l_production_element dbms_xmldom.DOMElement;
l_production_node dbms_xmldom.DOMNode;
-- production XML elements, node, text
l_prod_element dbms_xmldom.DOMElement;
l_prod_node dbms_xmldom.DOMNode;
l_prod_t_node dbms_xmldom.DOMNode;
l_prod_text dbms_xmldom.DOMText;
-- production XML elements, node, text, node
CURSOR c_production
IS SELECT 'test type 1', as prodCategoryType
'prod status 1' as prodStatusType
from dual
UNION
SELECT 'test type 2', as prodCategoryType
'prod status 2' as prodStatusType
from dual;
BEGIN
UTL_FILE.FCLOSE_ALL; -- make sure all file handles are closed for session
l_file := UTL_FILE.fopen(l_extract_dir , 'Sample2.dat', 'w', 32767);
-- Create an empty XML document
l_domdoc := dbms_xmldom.newDomDocument;
-- Create a root node
l_root_node := dbms_xmldom.makeNode(l_domdoc);
-- Create a message root node
l_message_node := dbms_xmldom.appendChild( l_root_node, dbms_xmldom.makeNode(dbms_xmldom.createElement(l_domdoc, 'message' ))
);
FOR production_rec in c_production LOOP
l_production_element := dbms_xmldom.createElement(l_domdoc, 'production' );
l_production_node := dbms_xmldom.appendChild(l_message_node,dbms_xmldom.makeNode(l_production_element));
-- prodCategoryType
l_prod_element := dbms_xmldom.createElement(l_domdoc, 'prodCategoryType' );
l_prod_node := dbms_xmldom.appendChild(l_production_node,dbms_xmldom.makeNode(l_prod_element));
l_prod_text := dbms_xmldom.createTextNode(l_domdoc, production_rec.prodCategoryType );
l_prod_t_node := dbms_xmldom.appendChild(l_prod_node,dbms_xmldom.makeNode(l_prod_text));
-- prodStatusType
l_prod_element := dbms_xmldom.createElement(l_domdoc, 'prodStatusType');
l_prod_node := dbms_xmldom.appendChild(l_production_node,dbms_xmldom.makeNode(l_prod_element));
l_prod_text := dbms_xmldom.createTextNode(l_domdoc, production_rec.prodStatusType);
l_prod_t_node := dbms_xmldom.appendChild(l_prod_node,dbms_xmldom.makeNode(l_prod_text));
l_xmltype := dbms_xmldom.getXmlType(l_domdoc);
l_clob := l_xmltype.getClobVal;
DBMS_LOB.read (l_clob, l_amount, l_pos, l_buffer);
UTL_FILE.put(l_file, l_buffer);
l_pos := l_pos + l_amount;
END LOOP;
dbms_xmldom.freeDocument(l_domdoc);
UTL_FILE.fclose(l_file);
END;
答案 0 :(得分:0)
你真的做错了两件事。好吧,三个。您期望的输出不是有效的XML,因为没有根节点;你可能刚刚省略了(AV-XML?),但目前尚不清楚。
您实际生成的内容虽然有效,但不是您期望的格式。在循环的第一次迭代l_xmltype
包含:
<message>
<production>
<prodCategoryType>test type 1</prodCategoryType>
<prodStatusType>prod status 1</prodStatusType>
</production>
</message>
......这就是你的期望。但是在第二个循环之后,第二个生产节点被插入到同一个消息节点下,所以你有:
<message>
<production>
<prodCategoryType>test type 1</prodCategoryType>
<prodStatusType>prod status 1</prodStatusType>
</production>
<production>
<prodCategoryType>test type 2</prodCategoryType>
<prodStatusType>prod status 2</prodStatusType>
</production>
</message>
当您第一次写出文件时,您将l_pos
留在结束</message>
标记的末尾,并且您假设您拥有您希望看到的结构,这意味着在下一个循环中,下一个char将是第二个<message>
标记的开头。但由于(单个)结束标记现在已移动,l_pos
实际上现在位于新插入的第二个<production>
标记的中间。读取从该点开始,因此从该开始标记的on>
部分开始。
您应该做的主要事情是将XML的生成与输出分离到文件。有一个循环来构建你正在做的DOM,然后一个单独的循环将XML写入文件:
...
l_prod_t_node := dbms_xmldom.appendChild(l_prod_node,dbms_xmldom.makeNode(l_prod_text));
/* Remove all existing conversion/writing from the first loop
l_xmltype := dbms_xmldom.getXmlType(l_domdoc);
l_clob := l_xmltype.getClobVal;
DBMS_LOB.read (l_clob, l_amount, l_pos, l_buffer);
UTL_FILE.put(l_file, l_buffer);
l_pos := l_pos + l_amount;
*/
END LOOP;
WHILE l_pos <= dbms_lob.getlength(l_clob) LOOP
DBMS_LOB.read (l_clob, l_amount, l_pos, l_buffer);
UTL_FILE.put(l_file, l_buffer);
UTL_FILE.fflush(l_file);
l_pos := l_pos + l_amount;
END LOOP;
UTL_FILE.fclose(l_file);
END;
/
然后,您将拥有一个反映您正在生成的实际XML的文件。然后,您可以调整生成以具有不同的根节点,并在循环内添加消息和生产节点。只需将l_message_node := ...
行移动到第一个循环中,就可以得到问题中的结构。