title: XML Tag breaking in the middle when Chunking XMLTYPE to CLOB
body: <p>We have a procedure that writes a XML File using SQL and we're asked to improve it's performance. Currently, it prints the XML line-by-line like the code below:</p>
  
  <pre><code>begin
  
      dbms_output.put_line('&lt;tns:jpk&gt;');
  
      -- header section
      for i in (select xmlelement("tns:header", header_num)
                      ,xmlelement("tns:customer", customer_name)
                      ,xmlelement("tns:po_number", po_number) li_xml
                from  header_tbl) loop
  
          dbms_output.put_line( i.li_xml.getclobval() );
  
          dbms_output.put_line('&lt;tns:lines&gt;');
  
          -- Lines section    
          for x in (select xmlelement("tns:line_num", line_num)
                      ,xmlelement("tns:order", order_dtl)
                      ,xmlelement("tns:qty", qty)
                    from  Lines_tbl) lx loop
  
              dbms_output.put_line( x.lx_xml.getclobval() );
  
              dbms_output.put_line('&lt;tns:Summary&gt;');
  
              -- Summary section  
              for y in (select xmlelement("tns:sum_num", sum_num)
                          ,xmlelement("tns:total_amt, total_amt)
                          ,xmlelement("tns:total_qty, total_qty)
                      from  Summary_Tbl) lc_xml loop
  
                  dbms_output.put_line( y.lc_xml.getclobval() );
  
              end loop;
  
              dbms_output.put_line('&lt;tns:Summary&gt;');
  
          dbms_output.put_line('&lt;/tns:lines&gt;');
  
          end loop;
  
      end loop;
  
      dbms_output.put_line('&lt;/tns:jpk&gt;');
  
  end;
  </code></pre>
  
  <p>the above sample code looks like this:</p>
  
  <pre><code>&lt;tns:jpk&gt;
      &lt;tns:header&gt;1&lt;/tns:header&gt;
      &lt;tns:customer&gt;1000&lt;/tns:customer&gt;
      &lt;tns:po_number&gt;909090&lt;/tns:po_number&gt;
      &lt;tns:lines&gt;
          &lt;tns:line_num&gt;1&lt;/tns:line_num&gt;
          &lt;tns:order&gt;Other FA Open Asset Cost Pozostale Srodki Trwale -Wartosc poczatkowa&lt;/tns:order&gt;
          &lt;tns:qty&gt;1&lt;/tns:qty&gt;
          &lt;tns:Summary&gt;
              &lt;tns:sum_num&gt;1&lt;/tns:sum_num&gt;
              &lt;tns:total_amt&gt;1000&lt;/tns:total_amt&gt;
              &lt;tns:total_qty&gt;1&lt;/tns:total_qty&gt;
          &lt;/tns:Summary&gt;
      &lt;/tns:lines&gt;
  &lt;/tns:jpk&gt;
  </code></pre>
  
  <p>I've managed to make it a bit faster by using a different approach, like the code below:</p>
  
  <pre><code>declare 
  
      xml_c xmltype;
  
      procedure print_clob( p_clob in clob ) is
          v_offset number := 1;
          v_chunk_size number := 10000;
          --v_chunk_size number := 32767;
        begin
          loop
            exit when v_offset &gt; dbms_lob.getlength(p_clob);
            dbms_output.put_line( dbms_lob.substr( p_clob, v_chunk_size, v_offset ) );
  
            v_offset := v_offset + v_chunk_size;
          end loop;
  
       EXCEPTION
          WHEN OTHERS THEN
              dbms_output.put_line('print_clob. others ' || SQLERRM);
      end print_clob;   
  
  begin
  
      select  xmlagg(xmlconcat("&lt;tns:jpk&gt;",
          -- header section
          (select xmlagg(xmlconcat(
               xmlelement("tns:header", header_num)
              ,xmlelement("tns:customer", customer_name)
              ,xmlelement("tns:po_number", po_number)
              ,xmlelement("tns:lines", 
              -- lines section
              ,(select 
                  xmlagg(xmlconcat(
                      xmlelement("tns:line_num", line_num)
                  ,   xmlelement("tns:order", order_dtl)
                  ,   xmlelement("tns:qty", qty)
                  ,   (select 
                          xmlagg(xmlconcat(
                              xmlelement("tns:sum_num", sum_num)
                          ,   xmlelement("tns:total_amt", total_amt)
                          ,   xmlelement("tns:total_qty", total_qty)))
                      from  Summary_Tbl)
                  ))
                  from  Lines_tbl)
                  )
              ))
          from    header_tbl)
      ))
      into    xml_c
      from    dual;
  
      print_clob( xml_c.getclobval );
  
  end;
  </code></pre>
  
  <p>The above code makes a really long XML, and cuts it up to pieces and prints it.
  It works fine and faster based on the execution times.
  However, whenever there's a really long piece of string, the output sometimes gets skwered like below:</p>
  
  <pre><code>&lt;tns:jpk&gt;
      &lt;tns:header&gt;1&lt;/tns:header&gt;
      &lt;tns:customer&gt;1000&lt;/tns:customer&gt;
      &lt;tns:po_number&gt;909090&lt;/tns:po_number&gt;
      &lt;tns:lines&gt;
          &lt;tns:line_num&gt;1&lt;/tns:line_num&gt;
          &lt;tns:order&gt;Other FA Open Asset Cost Pozostale 
  Srodki Trwale -Wartosc poczatkowa&lt;/tns:order&gt;
          &lt;tns:qty&gt;1&lt;/tns:qty&gt;
          &lt;tns:Summary&gt;
              &lt;tns:sum_num&gt;1&lt;/tns:sum_num&gt;
              &lt;tns:total_amt&gt;1000&lt;/tns:total_amt&gt;
              &lt;tns:total_qty&gt;1&lt;/tns:total_qty&gt;
          &lt;/tns:Summary&gt;
      &lt;/tns:lines&gt;
  &lt;/tns:jpk&gt;
  </code></pre>
  
  <p>Is there a way for me to find out if the tag and it's contents will exceed the limit before I print it?</p>