https://livesql.oracle.com/apex/livesql/file/content_ET2CD8U5GO17VY2H0CJ8REEWL.html 11g Release 2 XE, 12c SE Release 1, 12c SE Release 2
Date+Time in XML when converting from cursor
Hi Chris, Connor, Maria,
I'm working on utPLSQL v3 project with few of colleagues and I'm facing a big challenge.
I want to leverage XML methods of SQL or PL/SQL to convert any cursor into XML but there is a catch.
Our functionality needs to be able to convert any cursor into XMLTYPE. The cursor will be already open, when entering utPLSQL code.
I've realized, that Oracle is converting DATE datatype to XML element using NLS session settings that were defined at the time the cursor was opened. The trouble is that the session NLS settings can be set into anything (not under control of the framework) and usually the settings are set to loose TIME and only include the DATE information. Incomplete information about DATE/TIME is making cursor-to-XML loose information (sometimes really important).
Similar difficulties were already described by Finn on Oracle 10g.
https://ellebaek.wordpress.com/2011/01/27/converting-between-oracle-data-and-xml/ I have tested it on 11g XE, 12.1 and 12.2 - and can't see way around it.
Is there a way to influence XML conversion of DATE datatype when using:
- XMLSERIALIZE(cursor)
- XMLTYPE.createXML(cursor)
- DBMS_XMLGEN
Also, when converting to XML using XMLSERIALIZE or XMLTYPE.createXML, is there an option to include NULL columns as empty elements?
I'd really like to be able to have full control over how my XML is formatted/generated.
Thanks,
Jacek
You can use dbms_xmlgen.restartQuery to reprocess the query. This will pick up your new NLS settings after you run it:
declare
c sys_refcursor;
ctx number;
xdoc xmltype;
begin
execute immediate q'[alter session set nls_date_format = 'yyyy-mm-dd']';
open c for select sysdate from dual;
execute immediate q'[alter session set nls_date_format = 'yyyy-mm-dd"T"hh24:mi:ss']';
ctx := dbms_xmlgen.newContext(c);
dbms_xmlgen.restartQuery(ctx);
xdoc := dbms_xmlgen.getxmltype(ctx);
dbms_output.put_line(xdoc.getclobval());
execute immediate q'[alter session set nls_date_format = 'dd-MON-yyyy']';
dbms_xmlgen.restartQuery(ctx);
xdoc := dbms_xmlgen.getxmltype(ctx);
dbms_output.put_line(xdoc.getclobval());
end;
/
<ROWSET>
<ROW>
<SYSDATE>2017-04-11T02:51:45</SYSDATE>
</ROW>
</ROWSET>
<ROWSET>
<ROW>
<SYSDATE>11-APR-2017</SYSDATE>
</ROW>
</ROWSET>
http://docs.oracle.com/cd/E11882_01/appdev.112/e40758/d_xmlgen.htm#ARPLS69862 I'm no XML expert, but it looks like the "show|hide defaults" option of XMLserailize may help you with displaying null elements (if you have a stylesheet):
http://docs.oracle.com/database/122/SQLRF/XMLSERIALIZE.htm#SQLRF06231