【问题标题】:Incorrect format in XML output file and I'm not sure whyXML 输出文件中的格式不正确,我不知道为什么
【发布时间】:2016-07-11 01:36:32
【问题描述】:

下面是从 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>

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

【问题讨论】:

    标签: xml plsql oracle11g format


    【解决方案1】:

    你真的做错了两件事。嗯,三个。您期望的输出不是有效的 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 留在结束 &lt;/message&gt; 标记的末尾,并且您假设您具有您希望看到的结构,这意味着在下一个循环中下一个字符将是第二个 &lt;message&gt; 标记的开始。但是由于(单个)结束标记现在已经移动,l_pos 实际上现在位于新插入的第二个&lt;production&gt; 标记的中间。读取从该点开始,因此从该开始标记的on&gt; 部分开始。

    您应该做的主要事情是将 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 := ... 行移至第一个循环即可获得问题中的结构。

    【讨论】:

    • 这太棒了 Alex Poole。
    • 刚刚运行它,现在它得到的唯一问题是我认为达到最大 clob 并且不再打印并且部分打印半个选项卡见下文。 TEST1TEST_1_TESTTEST1
    • 所以我想我需要在生产节点节点的每次迭代中写入/附加到文件。
    • @ShaunKinnair - 将 CLOB 分块写入应该没问题。您不想将其分解为节点并独立编写它们。试图弄清楚发生了什么;您确定文件已被截断,而不仅仅是您查看它的方式?
    • 是的,它似乎被截断了我可以给你发送一个代码示例,但我无法在评论框中得到全部内容
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多