Can we do for HTML also?
AB, January 11, 2002 - 7:34 am UTC
Is there an HTML equivalent? I have no Oracle Web tools and won't be able to have either.
I currently have my intranet set up to monitor db activity. I have a UNIX box with a webserver daemon and a PC with a browser. Currently I call an HTML script on the UNIX box which calls a shell script. This shell script executes a package.procedure. The procedure "DBMS_OUTPUTs" a combination of html tags and the resultset from cursors. The shell script pipes this back to the browser. As dynamic as I can get with my set up, so an "html-generator" like the XML one above would be great.
January 11, 2002 - 10:59 am UTC
AB,
Oracle8.1.7 comes with an Apache web listener and MOD_PLSQL, an Apache add-on that lets you write PL/SQL procedures to produce web pages. If you have access to an 8.1.7 database, the code you need to install and configure the PL/SQL Web Toolkit is located in the $ORACLE_HOME/Apache/modplsql directory.
The PL/SQL Web Toolkit let's you spool data to an HTML buffer instead of the DBMS_OUTPUT buffer. The toolkit contains packages (with procedures and functions) for creating html. Using this approach, you could do something like this:
connect scott/tiger
create or replace package xml_reports as
procedure employees;
procedure departments;
end xml_reports;
/
create or replace package body xml_reports as
procedure to_html(p_xml in out nocopy clob) is
l_xml varchar2(30000);
l_line varchar2(2000);
l_amt pls_integer := 30000;
l_idx pls_integer := 1;
begin
for i in 1 .. ceil(dbms_lob.getlength(p_xml)/l_amt) loop
l_xml := dbms_lob.substr(p_xml, l_amt, l_idx);
loop
exit when l_xml is null;
l_line := substr(l_xml, 1, instr(l_xml, chr(10))-1);
-- THIS IS THE SQLPLUS OUTPUT STYLE
--dbms_output.put_line('|' || l_line);
-- THIS IS THE HTML OUTPUT STYLE
htp.put_line(l_line);
l_xml := substr(l_xml, instr(l_xml, chr(10))+1);
end loop;
end loop;
end to_html;
procedure employees
is
l_clob clob;
l_ctx dbms_xmlgen.ctxHandle;
l_sql varchar2( 400 );
begin
l_sql := 'select *
from emp';
l_ctx := dbms_xmlgen.newContext( l_sql );
l_clob := dbms_xmlgen.getXml( l_ctx );
to_html( l_clob );
end employees;
procedure departments
is
l_clob clob;
l_ctx dbms_xmlgen.ctxHandle;
l_sql varchar2( 400 );
begin
l_sql := 'select *
from dept';
l_ctx := dbms_xmlgen.newContext( l_sql );
l_clob := dbms_xmlgen.getXml( l_ctx );
to_html( l_clob );
end departments;
end xml_reports;
/
show error
With this package procedure, I could put this in my browser:
</code>
http://servername:port/pls/dbconfig/xml_reports.employees
...and get the following results in my browser:
<?xml version="1.0"?>
<ROWSET>
<ROW>
<EMPNO>7369</EMPNO>
<ENAME>SMITH</ENAME>
<JOB>CLERK</JOB>
<MGR>7902</MGR>
<HIREDATE>17-DEC-80</HIREDATE>
<SAL>800</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7499</EMPNO>
<ENAME>ALLEN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>20-FEB-81</HIREDATE>
<SAL>1600</SAL>
<COMM>300</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7521</EMPNO>
<ENAME>WARD</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>22-FEB-81</HIREDATE>
<SAL>1250</SAL>
<COMM>500</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7566</EMPNO>
<ENAME>JONES</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>02-APR-81</HIREDATE>
<SAL>2975</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7654</EMPNO>
<ENAME>MARTIN</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>28-SEP-81</HIREDATE>
<SAL>1250</SAL>
<COMM>1400</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7698</EMPNO>
<ENAME>BLAKE</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>01-MAY-81</HIREDATE>
<SAL>2850</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7782</EMPNO>
<ENAME>CLARK</ENAME>
<JOB>MANAGER</JOB>
<MGR>7839</MGR>
<HIREDATE>09-JUN-81</HIREDATE>
<SAL>2450</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7788</EMPNO>
<ENAME>SCOTT</ENAME>
<JOB>ANALYST</JOB>
<MGR>7566</MGR>
<HIREDATE>19-APR-87</HIREDATE>
<SAL>3000</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7839</EMPNO>
<ENAME>KING</ENAME>
<JOB>PRESIDENT</JOB>
<HIREDATE>17-NOV-81</HIREDATE>
<SAL>5000</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
<ROW>
<EMPNO>7844</EMPNO>
<ENAME>TURNER</ENAME>
<JOB>SALESMAN</JOB>
<MGR>7698</MGR>
<HIREDATE>08-SEP-81</HIREDATE>
<SAL>1500</SAL>
<COMM>0</COMM>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7876</EMPNO>
<ENAME>ADAMS</ENAME>
<JOB>CLERK</JOB>
<MGR>7788</MGR>
<HIREDATE>23-MAY-87</HIREDATE>
<SAL>1100</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7900</EMPNO>
<ENAME>JAMES</ENAME>
<JOB>CLERK</JOB>
<MGR>7698</MGR>
<HIREDATE>03-DEC-81</HIREDATE>
<SAL>950</SAL>
<DEPTNO>30</DEPTNO>
</ROW>
<ROW>
<EMPNO>7902</EMPNO>
<ENAME>FORD</ENAME>
<JOB>ANALYST</JOB>
<MGR>7566</MGR>
<HIREDATE>03-DEC-81</HIREDATE>
<SAL>3000</SAL>
<DEPTNO>20</DEPTNO>
</ROW>
<ROW>
<EMPNO>7934</EMPNO>
<ENAME>MILLER</ENAME>
<JOB>CLERK</JOB>
<MGR>7782</MGR>
<HIREDATE>23-JAN-82</HIREDATE>
<SAL>1300</SAL>
<DEPTNO>10</DEPTNO>
</ROW>
</ROWSET>
For more information on the packages that make up the package, look here:
http://db.lib.vt.edu/ows-adoc/psqlwtlk.htm <code>
I hope that helps!
-SEAN- ;-)
PL/SQL to HTML
AB, January 11, 2002 - 11:10 am UTC
Tom,
Thankyou very much. This was exactly what I was looking for. I just need to work out how to format the output into grids etc now.
BTW, you are THE Oracle resource on the www. If I had as many people praising me as they do you, I'd have the ego the size of a rock star !!!
While I'm at it, your book is AMAZING also. Possibly the best actually. We don't need continual syntax manuals, we need APPROACH manuals, and you sure are changing the way I approach my applications.
Thanks again.
AB
XMLGEN and Cursors
Edgar, January 15, 2002 - 6:20 am UTC
Hello Tom and Sean!
This is all great, that we can use dbms_xmlgen to generate xml directrly from PL/SQL, but as I can see in manuals dbms_xmlgen.newContext() accepts parameter as simple static sql, from this site we all know that static sql is evil and that we have to use binding capabilities. Is there a way to generate xml from select passing as argument cursor or something like this?
January 15, 2002 - 9:34 am UTC
Hi Edgar Sean here...
Yes good point, I prolly should have included the bind variables as a part of the example... There are a couple of ways to handle this. Luckily, in DBMS_XMLQUERY we have the SETBINDVALUE procedure, so you could code it this way:
SQL> create or replace function get_emps_in_dept( p_deptno in number )
2 return clob
3 is
4 l_ctx dbms_xmlquery.ctxType;
5 l_sql varchar2(100);
6 l_xml clob;
7 begin
8 l_sql := 'select * from emp where deptno = :deptno';
9 dbms_lob.createtemporary( l_xml, true, dbms_lob.session );
10 l_ctx := dbms_xmlquery.newContext( l_sql );
11
12 dbms_xmlquery.setbindvalue( l_ctx, 'deptno', p_deptno );
13
14 dbms_xmlquery.setRaiseNoRowsException( l_ctx,false );
15
16 -- get the xml fm the context
17 l_xml := dbms_xmlquery.getXML( l_ctx );
18
19 dbms_xmlquery.closeContext(l_ctx);
20 return l_xml;
21 exception
22 when others then
23 dbms_xmlquery.closeContext(l_ctx);
24 raise;
25 end get_emps_in_dept;
26 /
Function created.
Then, if we test it, we can look in the v$sqlarea for matches:
SQL> declare
2 l_clob clob;
3 begin
4 l_clob := get_emps_in_dept( 10 );
5 end;
6 /
PL/SQL procedure successfully completed.
SQL> select count(*), executions
2 from v$sqlarea
3 where sql_text like 'select * from emp where deptno =%'
4 group by executions;
COUNT(*) EXECUTIONS
---------- ----------
1 1
If we run it a whole bunch of times, we get the same response:
SQL> declare
2 l_clob clob;
3 begin
4 for i in 1 .. 100 loop
5 l_clob := get_emps_in_dept( i );
6 end loop;
7 end;
8 /
PL/SQL procedure successfully completed.
SQL>
SQL> select count(*), executions
2 from v$sqlarea
3 where sql_text like 'select * from emp where deptno =%'
4 group by executions;
COUNT(*) EXECUTIONS
---------- ----------
1 101
In the case where an API doesn't have the ability to set bind variables, there are a couple of approaches you can use. Cursor sharing is the way to tell the database to do this for us:
execute immediate 'alter session set cursor_sharing = force';
then call the API
execute immediate 'alter session set cursor_sharing = exact';
will do it in 8.1.6 and up (an autobinder feature -- good for wierd cases like this)
As well, you can use the technique outlined on:
http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:1288401763279
using an application context. You would use dbms_session.set_context to "bind" instead of dbms_sql.bind_variable.
Using XML
reader, April 26, 2003 - 8:05 am UTC
SQL>desc employees ;
Name Null? Type
----------------------------------------------------- -----
ID NUMBER
FNAME VARCHAR2(100)
LNAME VARCHAR2(100)
SQL>SELECT XMLELEMENT ( "Emp", XMLATTRIBUTES (e.id,e.fname ||' ' || e.lname AS "name")) AS "result" FROM employees e;
/
result()
============================================================
XMLTYPE()
XMLTYPE()
XMLTYPE()
what is wrong in this, i am not getting the expected output. please clarify.
Thanks
April 26, 2003 - 8:50 am UTC
works for me --
scott@ORA920LAP> sELECT XMLELEMENT ( "Emp", XMLATTRIBUTES (e.empno,e.ename ||' ' || e.job AS
2 "name")) AS "result" FROM emp e;
result
-----------------------------------------------------------------------------------------------------------------------------------
<Emp EMPNO="7369" name="SMITH CLERK"></Emp>
<Emp EMPNO="7499" name="ALLEN SALESMAN"></Emp>
<Emp EMPNO="7521" name="WARD SALESMAN"></Emp>
<Emp EMPNO="7566" name="JONES MANAGER"></Emp>
<Emp EMPNO="7654" name="MARTIN SALESMAN"></Emp>
<Emp EMPNO="7698" name="BLAKE MANAGER"></Emp>
<Emp EMPNO="7782" name="CLARK MANAGER"></Emp>
<Emp EMPNO="7788" name="SCOTT ANALYST"></Emp>
<Emp EMPNO="7839" name="KING PRESIDENT"></Emp>
<Emp EMPNO="7844" name="TURNER SALESMAN"></Emp>
<Emp EMPNO="7876" name="ADAMS CLERK"></Emp>
<Emp EMPNO="7900" name="JAMES CLERK"></Emp>
<Emp EMPNO="7902" name="FORD ANALYST"></Emp>
<Emp EMPNO="7934" name="MILLER CLERK"></Emp>
14 rows selected.
Using XML
reader, April 26, 2003 - 9:04 am UTC
SQL>select xmlelement("Employees",
2 xmlagg(
3 xmlelement(
4 "Employee",
5 xmlforest(empno, ename, sal)))) as "result"
6 from emp
7 ;
result()
============================================================
XMLTYPE()
I am stuck here,.. not able to proceed. can it be because of any settings that needs to be changed. remember it was working earlier..
April 26, 2003 - 11:50 am UTC
it works for me.
I do not remember that it was working earlier -- i've no clue who you are.
You are not cutting and pasting from sqlplus -- result() wouldn't appear there, it would be result and we use ---- not ======= so I can only guess you are using toad or something else and they are punting when it comes to displaying an object type.
A reader, April 26, 2003 - 12:14 pm UTC
Tom,
trust me - It didnt work...
i restarted and put the same query - it worked.
i have been out for dinner, after 45 minutes, i read your reply, thought i would say its working now - but again the query failed.
the sqlplus which was working - i still have it opened. opened a new session, its failing now. !
SQL> select xmlelement("Employees",
2 xmlagg(
3 xmlelement(
4 "Employee",
5 xmlforest(empno, ename, sal)))) as "result"
6 from emp
7 ;
result()
============================================================
XMLTYPE()
the other window which is working :
SQL> select xmlelement("Employees",
2 xmlagg(
3 xmlelement(
4 "Employee",
5 xmlforest(empno, ename, sal)))) as "result"
6 from emp
7 ;
result
--------------------------------------------------------------------------------
<Employees>
<Employee>
<EMPNO>7369</EMPNO>
<ENAME>SMITH</ENAME>
<SAL>800</SAL>
</Employee>
<Employee>
<EMPNO>7499</EMPNO>
<ENAME>ALLEN</ENAME>
<SAL>1600</SAL>
</Employee>
result
--------------------------------------------------------------------------------
<Employee>
<EMPNO>7521</EMPNO>
.... continues
<SAL>1300</SAL>
</Employee>
</Employees>
may be i need to restart and test it again.
I would never waste your time, that you dedicate for us. i daily visit your site and learn a lot.
Thanks
Shailesh, May 21, 2003 - 7:21 am UTC
I created package xml_reports and two procedures as given
in the example. However when i place the link
http://172.17.19.140:80/xml_reports.employees I get error
Page cannot be found.
Also there is a message given
HTTP-404 - File not found.
My apache server is running on
SQL> host
$ ps -ef|grep apache
www 3363 1914 0 Apr 11 ? 0:00 /opt/apache/bin/httpd
www 1926 1914 0 Apr 10 ? 0:00 /opt/apache/bin/httpd
root 1914 1 0 Apr 10 ? 2:15 /opt/apache/bin/httpd
www 1927 1914 0 Apr 10 ? 0:00 /opt/apache/bin/httpd
www 1928 1914 0 Apr 10 ? 0:00 /opt/apache/bin/httpd
www 1929 1914 0 Apr 10 ? 0:00 /opt/apache/bin/httpd
www 1930 1914 0 Apr 10 ? 0:00 /opt/apache/bin/httpd
www 11484 1914 0 Apr 24 ? 0:00 /opt/apache/bin/httpd
www 17274 1914 0 Apr 17 ? 0:00 /opt/apache/bin/httpd
www 20836 1914 0 Apr 30 ? 0:00 /opt/apache/bin/httpd
oracle9i 17638 16418 0 16:37:13 pts/tk 0:00 grep apache
The OS is HP-UX 11i and db version is 9.0.1.4.
please help
Regards
Shailesh
How can we sort the extract() results?
A Reader, July 16, 2003 - 4:13 pm UTC
We have a query like the following:
select * from (select extract(xmldetail, '/XMLDetail/Detail/text()')
from t_with_xmltype) order by 1
*
We get the following error:
ERROR at line 1:
ORA-22950: cannot ORDER objects without MAP or ORDER method
How can we sort the result set returned from an XML query?
Thank you very much for your help.
July 16, 2003 - 4:21 pm UTC
well, that is an "object", an XML document, being returned.
if the detail is a scalar, perhaps you meant to use extractvalue?
Generate XML from Type as Table of Object
JK, July 25, 2003 - 6:27 pm UTC
Hi Tom,
Can you please suggest what is wrong in this?
CREATE OR REPLACE TYPE datastack AS OBJECT (
ATTRIB_NAME VARCHAR2(40), --This should be the Tag
ATTRIB_VALUE VARCHAR2(40)); -- This is the value
Inside my Procedure I have
TYPE datacontext is TABLE OF datastack;
dump_data_stack datacontext := datacontext();
The dump_data_stack is updated with data. This is something similar to a call_stack but will be populated with data from within the procedures. If there is an exception in the procedure, this data_stack will be dumped into error_log table as a XML.
Here comes my problem.
l_ctx := dbms_xmlquery.newContext(
'select * from THE ( select cast( dump_data_stack as datacontext )from dual ) a');
l_xml_payload := dbms_xmlquery.getXml(l_ctx);
throws
"XML IS: ***<?xml version = '1.0'?>
<ERROR>oracle.xml.sql.OracleXMLSQLException:
ORA-00902: invalid datatype" this error.
I couldnt resolve it. So, i tried this:
FOR stack_index IN 1 .. top_of_data_stack
LOOP
l_attrib_name := '"' || dump_data_stack (stack_index).attrib_name || '"';
SELECT XMLElement (l_attrib_name,
dump_data_stack (stack_index).attrib_value )
INTO l_xml
FROM DUAL;
l_xml_payload := l_xml.getClobVal();
l_call_stack_text := l_call_stack_text || l_xml_payload;
This prints as
"<L_ATTRIB_NAME>234567899</L_ATTRIB_NAME><L_ATTRIB_NAME>Mary M Beth</L_ATTRIB_NAME><L_ATTRIB_NAME>Margin Account</L_ATTRIB_NAME> ..."
I expected/require it to be something like this:
"<SSN>234567899</SSN><NAME>Mary M Beth</NAME> <ACCOUNT>Margin Account</ACCOUNT> ..."
Can you please suggest some option? Also is there a better way to dump data log to the table? I update the stack through the course of the procedure and then plan to dump it.
Thanks & Regards
JK
July 25, 2003 - 8:41 pm UTC
datacontext must be defined at the sql level, it is not visible to SQL when it is defined in that procedure.
How to separate the xml results
Yong Wu, September 03, 2003 - 8:14 pm UTC
I ran the following query and expect results like
Administrative
Business
But the results are always concatenated. How to fix the problem?
Thanks,
SQL> l
1 begin
2 for c in (select x.content.extract('/School//Category/@CodeName').getStringVal()
3 Category
4 from xml_data x) loop
5 dbms_output.put_line(c.category);
6 end loop;
7* end ;
SQL> /
AdministrativeBusiness
September 04, 2003 - 8:49 am UTC
hmm, no table xml_data in my database
no xml to peek at.
sort of hard to say anything without a full, yet concise and simple, test case (which I find I frequently find my own mistakes in when putting it together)
Here is test data
Yong Wu, September 04, 2003 - 3:19 pm UTC
Tom,
Here is the test data. Thanks for your help.
create table xml_data
(id number,
name varchar2(60),
status varchar2(20),
created_date date default sysdate,
content xmltype);
insert into xml_data values(1,'EDU Program','New',sysdate,
'<School codekey="3028" Name="Vatterott College">
<QualificationMajor CodeName=”Undergraduate” DisplayName="Undergraduate" Description=”Undergraduate”>
<QualificationMinor CodeName=”Associate” DisplayName="Associate" Description="Associate">
<QualificationMinor CodeName=”Bachelor” DisplayName="Bachelor" Description=” Bachelor">
</Qualification>
<QualificationMajor CodeName="Graduate" DisplayName="Graduate" Description=”Undergraduate”>
<QualificationMinor CodeName="Bachelor" DisplayName="Bachelor" Description="Bachelor">
<QualificationMinor CodeName="Doctorate" DisplayName="Doctorate" Description="Doctorate">
</Qualification>
<Campus codekey="302072" Name="Cleveland">
<Category CodeName="Administrative" DisplayName="Administrative">
<SubCategory CodeName="BUSINESSADMINISTRATIVEASSISTANT(1OF2)" DisplayName="Business Administrative Assistant">
<Program CodeName="210AASD" DisplayName="Administrative Applications Specialist" AlternativeName="210AASD" />
<Program CodeName="210AOSA" DisplayName="Administrative Office Specialist" AlternativeName="210AOSA" />
<Program CodeName="210COAD" DisplayName="Computer Office Assistant" AlternativeName="210COAD" />
</SubCategory>
</Category>
<Category CodeName="Business" DisplayName="Business">
<SubCategory CodeName="ACCOUNTING(1OF2)" DisplayName="Accounting">
<Program CodeName="210ACCA" DisplayName="Accounting " AlternativeName="210ACCA" />
</SubCategory>
</Category>
</Campus>
</School>');
SQL> l
1 begin
2 for c in (select x.content.extract('/School//Category/@CodeName').getStringVal()
3 Category
4 from xml_data x) loop
5 dbms_output.put_line(c.category);
6 end loop;
7* end ;
SQL> /
AdministrativeBusiness
September 05, 2003 - 3:14 pm UTC
sorry -- this example is so far away from even slightly working.....
you have an xmltype, you are inserting char
you have a <QualificationMajor> tag that is ended with /Qualification
you have QualificationMinor tags that are not even ended....
please, make sure the stuff at least *runs*
Yong Wu, September 05, 2003 - 3:39 pm UTC
I am realy sorry for posting wrong sql. Here is the query.
insert into xml_data values(1,'EDU Program','New',sysdate,
xmltype('<School codekey="3028" Name="Vatterott College">
<QualificationMajor CodeName="Undergraduate" DisplayName="Undergraduate" Description="Undergraduate">
<QualificationMinor CodeName="Associate" DisplayName="Associate" Description="Associate" />
<QualificationMinor CodeName="Bachelor" DisplayName="Bachelor" Description="Bachelor" />
</QualificationMajor>
<QualificationMajor CodeName="Graduate" DisplayName="Graduate" Description="Undergraduate">
<QualificationMinor CodeName="Bachelor" DisplayName="Bachelor" Description="Bachelor" />
<QualificationMinor CodeName="Doctorate" DisplayName="Doctorate" Description="Doctorate" />
</QualificationMajor>
<Campus codekey="302072" Name="Cleveland">
<Category CodeName="Administrative" DisplayName="Administrative">
<SubCategory CodeName="BUSINESSADMINISTRATIVEASSISTANT(1OF2)" DisplayName="Business Administrative Assistant">
<Program CodeName="210AASD" DisplayName="Administrative Applications Specialist" AlternativeName="210AASD" />
<Program CodeName="210AOSA" DisplayName="Administrative Office Specialist" AlternativeName="210AOSA" />
<Program CodeName="210COAD" DisplayName="Computer Office Assistant" AlternativeName="210COAD" />
</SubCategory>
</Category>
<Category CodeName="Business" DisplayName="Business">
<SubCategory CodeName="ACCOUNTING(1OF2)" DisplayName="Accounting">
<Program CodeName="210ACCA" DisplayName="Accounting " AlternativeName="210ACCA" />
</SubCategory>
</Category>
</Campus>
</School>'));
SQL> select x.content.extract('/School//Category/@CodeName').getStringVal()
2 Category
from xml_data x;
3
CATEGORY
--------------------------------------------------------------------------------
AdministrativeBusiness
SQL> select x.content.extract('/School//SubCategory/@CodeName').getStringVal()
2 SubCategory
3 from xml_data x;
SUBCATEGORY
--------------------------------------------------------------------------------
BUSINESSADMINISTRATIVEASSISTANT(1OF2)ACCOUNTING(1OF2)
Thanks for your help
Yong Wu, September 09, 2003 - 1:04 pm UTC
I tried another query it returns the same
SQL> select extract(content,'/School//SubCategory/@CodeName').getStringVal() from xml_data;
EXTRACT(CONTENT,'/SCHOOL//SUBCATEGORY/@CODENAME').GETSTRINGVAL()
--------------------------------------------------------------------------------
BUSINESSADMINISTRATIVEASSISTANT(1OF2)ACCOUNTING(1OF2)
I would like to know how to spit the results like
BUSINESSADMINISTRATIVEASSISTANT(1OF2)
ACCOUNTING(1OF2)
Thanks,
September 10, 2003 - 12:29 pm UTC
Hi Yong, Sean Dillon here. You want to use an operator in Oracle9iR2 called XMLSequence. You can read all about XMLSequence in the documentation (Oracle XML DB Developer's Handbook). XMLSequence turns an extract result into a set of XMLType documents instead of a single XMLType result set. You then use the TABLE function to turn that set of XMLType documents into a source from which you can query:
SQL> select extractvalue(value(d), '/SubCategory/@CodeName')
2 from xml_data x,
3 table( xmlsequence( extract(x.content, '/School//SubCategory') ) ) d
4 /
EXTRACTVALUE(VALUE(D),'/SUBCATEGORY/@CODENAME')
--------------------------------------------------------------------------------
BUSINESSADMINISTRATIVEASSISTANT(1OF2)
ACCOUNTING(1OF2)
Hope that helps!
Sean Dillon - Principal Technologist, Oracle Corporation
Author "Beginning Oracle Programming" www.amazon.com/exec/obidos/ASIN/186100690X
Yong Wu, September 10, 2003 - 1:54 pm UTC
Sean,
It works.
I follow Oracle on-line document Oracle9i XML Database Developer's Guide and didn't reach far enough to find a good example.
Great! It helpe me a lot.
Thanks,
Error in creating a xml schema
Yong Wu, September 10, 2003 - 2:14 pm UTC
Sean,
I tried to create/register a xml schema and got an error.
Would you please let me know what is wrong with this error or some setup problem?
create table po_tab(
id number,
po sys.XMLType
)
xmltype column po
XMLSCHEMA "</code>
http://www.oracle.com/PO.xsd" <code>
element "PurchaseOrder";
create table po_tab(
*
ERROR at line 1:
ORA-01001: invalid cursor
ORA-21700: object does not exist or is marked for delete
Thanks
September 10, 2003 - 8:13 pm UTC
thats not a valid url
---
Hi Sean here... in the SQL reference, look up the create table statement. Under the XML Schema explanation, it states if you specify an XMLSCHEMA for your column storage, you must have already registered the XML Schema with the database. Page 15-42:
"If you do specify an XMLSchema URL, you must already have registered the XMLSchema using the DBMS_XMLSCHEMA package."
You can lookup DBMS_XMLSCHEMA in the "Supplied PL/SQL Packages and Types Reference." Basically the REGISTER_SCHEMA procedure tells Oracle you will be storing XML according to a particular schema, and creates the underlying storage mechanism for that schema. For more information about this, you can read Chapter 5, Structured Mapping of XMLType of the "XML Database Developer's Guide". Hope that helps!
dynamic SQL with XML
vll, January 27, 2004 - 12:53 pm UTC
Hi, Tom!
Am I doing something wrong?
With direct SQL:
select xmlelement("RESULTS") into sc_xml.result from dual;
everything is fine (sc_xml.result is a package variable). When I'm trying to do it with dynamic SQL - i'm getting error:
strSQL := 'select xmlelement("RESULTS") into sc_xml.result from dual';
execute immediate strSQL;
error is:ORA-00905: missing keyword.
Is there any way to build XML queries dynamically?
Thank you very-very much!!!
January 27, 2004 - 1:17 pm UTC
INTO :variable
is a plsql thing. INTO is not sql.
strSQL := 'select xmlelement("RESULTS") from dual';
execute immediate strSQL into sc_xml.result;
Using XMLSequence
Raghu, February 19, 2004 - 9:35 am UTC
I have registered a xml schema in the database.
then i created a table based on the xml schema.
then i inserted the xml data into the table using the file from XML repository.
Here are the scripts.
CREATE TABLE TabL_FileContent
(
id NUMBER,
SequenceData XMLType,
FileContent BLOB
)
XMLTYPE COLUMN SequenceData
STORE AS OBJECT RELATIONAL
XMLSCHEMA "</code>
http://www.w3.org/2001/XMLSchema/XMLAblDaten.xsd" ELEMENT "MEPSequenceData";
INSERT INTO TabL_FileContent VALUES
( 1
,XMLTYPE(XDBURITYPE('/public/labor/ftp_path/xmlabldaten.xml').GetClob())
, EMPTY_BLOB()
)
/
When i issue this query
SELECT EXTRACT(SequenceData, '//VarSequData/VarSequDataRow/VarSequDataColumn/text()').GetClobVal()
FROM TabL_FileContent
WHERE ROWNUM = 1
/
i get the results in this way.
EXTRACT(SEQUENCEDATA,'//VARSEQUDATA/VARSEQUDATAROW/VARSEQUDATACOLUMN/TEXT()').GE
--------------------------------------------------------------------------------
10.52.5000101010010.52.50001010.52.5000101010010.52.50001010.52.5000101010010.52
.50001010.52.50001010.52.5000101010010.52.50001010.52.50001010.52.50001010.52.50
001010.52.50001010.52.5000101010010.52.500010
I want the results to be in record level one after another.So based on the above example i tried to use XMLSequence but without success.
Here is the query for which i do not get any result.
select extractvalue(value(d), '//VarSequData/VarSequDataRow/VarSequDataColumn')
from tabl_filecontent x,
table( xmlsequence( extract(x.sequencedata, '//VarSequData/VarSequDataRow/VarSequDataColumn') ) ) d
where rownum = 1
/
i just get blank. no result.
EXTRACTVALUE(VALUE(D),'//VARSEQUDATA/VARSEQUDATAROW/VARSEQUDATACOLUMN')
----------------------------------------------------------------------------------------------------
I am just attaching a part of the xml file becuae the entire file cannot be pasted here.
<?xml version="1.0" encoding="ISO-8859-1"?>
<MEPSequenceData xmlns="
http://www.w3.org/2001/XMLSchema/XMLAblDaten.xsd" xmlns:xdb="
http://xmlns.oracle.com/xdb" xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
http://www.w3.org/2001/XMLSchema/XMLAblDaten.xsd http://www.w3.org/2001/XMLSchema/XMLAblDaten.xsd" <code>Name="CR_SimpleSequencedaten" DataType="Sequencedata" Model="CR" VersionTemplate="1.0" VersionEditor="1.0" LastTimeStamp="20030219132346" LastUpdate="19.02.2003 13.23.46">
<Allgemein>
<AllgemeinRow TimeStamp="20030219132346">
<AllgemeinColumn id="Name" DataType="text">CR_Bedatung_Einschwingen</AllgemeinColumn>
<AllgemeinColumn id="Version" DataType="text">0.1</AllgemeinColumn>
<AllgemeinColumn id="Bemerkung" DataType="text">geaendert von Benutzer: demo</AllgemeinColumn>
<AllgemeinColumn id="letztes Update" DataType="text">19.02.2003 13.23.46</AllgemeinColumn>
</AllgemeinRow>
</Allgemein>
<!-- Teilablaeufe -->
<TA_Sequences>
<Sequence id="TA_01">
<Name>Partsequence PartOne</Name>
<ViewName>PartOne auf Englisch?</ViewName>
<MeasPoint id="TA_01_LPREV_00" Typ="Revolution">
<Name>Emi Revolution</Name>
<ViewName>Emi Revolution...</ViewName>
<PrgIdent>LPREV_01</PrgIdent>
<MeasPointSteps>
<MeasPointStep id="S_001" Nr="1">
<ViewName>Emi Revolution Schritt 1</ViewName>
<StepGeneral>
<StepGeneralRow TimeStamp="20030219132346">
<!--- Diese Daten sind von MeasPoint zu Lastpuntk verschieden
und sind zu jedem Zeitpunkt erweiterbar -->
<StepGeneralColumn id="Lastpunktanzeige" DataType="integer">1</StepGeneralColumn>
<StepGeneralColumn id="EMI_Huebe" DataType="integer">10</StepGeneralColumn>
<StepGeneralColumn id="Messwertaufnahme" DataType="double">1</StepGeneralColumn>
<StepGeneralColumn id="Wartezeit" DataType="double">0</StepGeneralColumn>
</StepGeneralRow>
</StepGeneral>
<SetPhase>
<SetVar id="p_Rail(ASAP)" Unit="bar" DataType="double">
<ViewName>p_Rail(ASAP)</ViewName>
<VarDescription>Hier kann ein beliebiger Text fuer die Beschreibung der Var stehen</VarDescription>
<VarDevice>Emi2</VarDevice>
<!-- dargestellt im Format -->
<DisplayFormat>%8.2f</DisplayFormat>
<!-- 4 Punkte Umrechnungsformel -->
<VarSequData>
<VarSequDataRow TimeStamp="20030219132346">
<VarSequDataColumn id="Sollwert" Unit="" DataType="double">10.5</VarSequDataColumn>
<VarSequDataColumn id="Toleranz" Unit="" DataType="double">2.5</VarSequDataColumn>
<VarSequDataColumn id="Beurteilung" Unit="" DataType="integer">0</VarSequDataColumn>
<VarSequDataColumn id="Bewertung" Unit="" DataType="integer">0</VarSequDataColumn>
<VarSequDataColumn id="Vorverarbeitung" Unit="" DataType="integer">0</VarSequDataColumn>
<VarSequDataColumn id="VorverarbeitungParameter" Unit="" DataType="integer">10</VarSequDataColumn>
<VarSequDataColumn id="Stepweite" Unit="" DataType="integer">10</VarSequDataColumn>
<VarSequDataColumn id="Stepanzahl" Unit="" DataType="integer">100</VarSequDataColumn>
</VarSequDataRow>
</VarSequData>
</SetVar>
</SetPhase>
<MeasPhase>
<MeasVar id="Q_quer(Emi2)" Unit="bar" DataType="double">
<ViewName>Q_quer(Emi2)</ViewName>
<VarDescription>Hier kann ein beliebiger Text fuer die Beschreibung der Var stehen</VarDescription>
<VarDevice>Emi2</VarDevice>
<VarSequData>
<VarSequDataRow TimeStamp="20030219132346">
<VarSequDataColumn id="Sollwert" Unit="" DataType="double">10.5</VarSequDataColumn>
<VarSequDataColumn id="Toleranz" Unit="" DataType="double">2.5</VarSequDataColumn>
<VarSequDataColumn id="Beurteilung" Unit="" DataType="integer">0</VarSequDataColumn>
<VarSequDataColumn id="Bewertung" Unit="" DataType="integer">0</VarSequDataColumn>
<VarSequDataColumn id="Vorverarbeitung" Unit="" DataType="integer">0</VarSequDataColumn>
<VarSequDataColumn id="VorverarbeitungParameter" Unit="" DataType="integer">10</VarSequDataColumn>
</VarSequDataRow>
</VarSequData>
Can you kindly help me out with this problem.
Should i place this question in new thread ?
Raghu, February 23, 2004 - 12:10 am UTC
Hi Tom,
Do i need to put the above question in a new thread.
I have posted it here becuase in the above discussions XMLSequence is being discussed.
Please let me know.
February 23, 2004 - 7:38 am UTC
I do not see all reviews -- and I cannot answer all of them either.
I asked someone else to look at this, xml is not my area of expertise, if they get time, they will.
Problem is solved.
Raghu, February 25, 2004 - 6:15 am UTC
i am posting this so that others can benefit from this.
In such situations you can provide namespace along with the xpath to EXTRACT and EXTRACTVALUE operators.
Here is the query.
SELECT EXTRACTVALUE(VALUE(x), '/StepGeneralColumn[@DataType="KonfigFile"]', 'xmlns="</code>
http://www.w3.org/2001/XMLSchema/XMLAblDaten.xsd"' FROM TabL_FileContent
, TABLE(XMLSEQUENCE(EXTRACT(SequenceData, '/MEPSequenceData//StepGeneralColumn', 'xmlns="
http://www.w3.org/2001/XMLSchema/XMLAblDaten.xsd"' <code>)) x
WHERE FileID = 1
/
Setting the dateformat using DBMS_XMLGEN
Nolan Tucker, March 09, 2004 - 4:56 pm UTC
Hi Tom and Sean,
This thread has lots of useful information. Thank you.
We're using dbms_xmlgen and passing it a resultset from a stored procedure. I'd like date fields generated in 'YYYY-MM-DD HH24:MM:SS' format. I don't see a procedure like
dbms_xmlgen.usenullattributeindicator that will do this. Can this be influenced by setting the session nls_date_format? If not how do I format? We're running Oracle9i Enterprise Edition Release 9.2.0.4.0.
This is a simplified version of what we're doing:
declare
test_cursor HDP_LocationDetail_PAK.LocationDetailCur;
resultset test_cursor%rowtype;
resultset_xml XMLTYPE;
resultsetrows integer;
resultsetsize integer;
l_ctx dbms_xmlgen.ctxHandle;
begin
HDP_LocationDetail_PRC(test_cursor,'Valexia','101815',TO_DATE('2003-05-15', 'YYYY-MM-DD'), TO_DATE('2003-06-30', 'YYYY-MM-DD');
l_ctx := dbms_xmlgen.newContext(test_cursor);
dbms_xmlgen.usenullattributeindicator(l_ctx,TRUE);
resultset_xml := dbms_xmlgen.getxml(l_ctx);
resultsetrows := dbms_xmlgen.getNumRowsProcessed(l_ctx);
dbms_output.put_line(''rowsprocessed=''||resultsetrows);
UPDATE vrp_ReportRuns SET enddate=SYSDATE, rowsreturned=resultsetrows,reportresultset=resultset_xml,
statuscode=0,statusmessage=''Success'',
nextrundate=NULL, failurecount=0;
dbms_xmlgen.closeContext(l_ctx);
commit;
end;
Thank you for your time.
Nolan
Okay - yes it works.
Nolan Tucker, March 18, 2004 - 4:39 pm UTC
I altered my session at the beginning of the procedure with
DBMS_SESSION.SET_NLS('NLS_DATE_FORMAT','''YYYY-MM-DD HH24:MI:SS''');
and found the XML datetype nodes are stored as 'YYYY-MM-DD HH24:MI:SS'.
XML extraction alternatives?
J, May 14, 2004 - 11:24 am UTC
Hello Tom.
Thanks for your services to the Oracle community (it's Most Appreciated). I have a situation like this: (sql*plus: 9.2.0.1.0, Database: 9.2.0.4.0)
create table jtest2
(p number primary key,
other_columns_etc varchar2(20),
r number);
begin
for i in 1..100
loop
execute immediate
'insert into jtest2(p) values (:val)'
using i;
end loop;
commit;
end;
-- --------------------------------------------------------
-- So create an xmlarray of JTEST2 rows that have null R's.
-- This array is passed to an RPC-procedure that figures
-- out the R's, and passes back the array with R values.
--
-- The following pseudo-replicates the returned array...
-- --------------------------------------------------------
declare
v_xml xmltype;
type tt_p is table of jtest2.p%type;
tab_p tt_p := tt_p();
type tt_r is table of jtest2.r%type;
tab_r tt_r := tt_r();
begin
select xmlelement
("SET",
(select xmlagg(xmlelement("ROW",xmlattributes(P,R)))
from
(select P,
other_columns_etc,
12 R -- mimics returned value
from jtest2
where r is null)
)
)
into v_xml
from dual;
-- -----------------------------------------------------
-- The XML string looks like this...
-- In real life (??), there's fluff attributes
-- in here that I don't care about.
--
-- <SET><ROW P="1" R="12"></ROW><ROW P="2" R="12"></ROW>
-- etc... </SET>
-- -----------------------------------------------------
-- Some stuff happens here...
-- -----------------------------------------------------
-- Load up P and R arrays.
-- These arrays are later used in a forall to go back
-- and update JTEST2.R columns (matching on P).
--
-- This takes about *82%* of the total procedural time.
-- (with 85k+ rows and full data regalia)
--
-- THE QUESTION (finally):
-- Are there any other approaches that I can use
-- to speed this up? I tried bulking into a type,
-- and ran a slug-o-tests, but no appreciable
-- difference in dbms_utility.get_time results
-- compared to this method.
-- -----------------------------------------------------
for xml_rec in
(select extractvalue(value(t),'/ROW@P') p,
extractvalue(value(t),'/ROW@R') r
from table(xmlsequence(v_xml.extract('/SET/ROW'))) t
)
loop
if (xml_rec.r is not null) then
tab_p.extend;
tab_p(tab_p.count) := xml_rec.p;
tab_r.extend;
tab_r(tab_r.count) := xml_rec.r;
end if;
end loop;
-- Then Forall update, More Stuff Happens, etc.
-- Thanks for your time, have a great weekend!!! - J
end;
XML Extraction Alternatives (part deux)
J, May 14, 2004 - 4:24 pm UTC
Hello Tom.
FYI, here's what has been tried so far:
1) Bulk load the extractvalue-related query into a tabtype based on an object type.
2) Bulk load the data into two procedure-defined arrays.
3) Load via a cursor "for" loop into two arrays.
4) Load via a cast/multiset (whoa, that was a slow one).
All of my attempts (except for #4) yield the same approximate throughput - about 100 rows/sec. I reduced the number of non-necessary attributes (leaving the returned xmltype with just the "P" and "R" attributes). That seemed to pick things up a bit, but only by 5-7% (which could be influenced by the fact that this is a shared Dev environment).
So... I'm wondering if this throughput rate is consistent with experiences using the extractvalue/xmlsequence method used above. Is there another option for extracting out specific attributes in an xml doc that might be quicker?
Many thanks!
- J
XML Extraction Alternatives
J, May 20, 2004 - 9:53 am UTC
G'Morning Tom.
Hope things are going well for you at the client site. Must be a good'un! I was wondering if you had any thoughts about the throughput rate for the:
select extractvalue(value(t),'/ROW@P') p,
extractvalue(value(t),'/ROW@R') r
from table(xmlsequence(lv_xml.extract('/SET/ROW'))) t
question. It's workable, but... are there other approaches? We ran a dbms_profiler on the process, and yep, about 82% of the total procedural time is spent on this one select statement. Tried the above-mentioned approaches and the times were similar. Am I missing anything, any parameters I should look at, can this be parallelized (if that's a word), etc? Thanks again.
- J
May 20, 2004 - 11:43 am UTC
well, if those were values I needed LOTS, i might consider extracting that out during the INSERT (since you insert once and query many many times)
Where is the class oracleXML ?
Randy King, May 20, 2004 - 3:43 pm UTC
Getting error while doing java OracleXML getXML -user "scott/tiger" "select * from emp where rownum < 5"
Exception in thread "main" java.lang.NoClassDefFoundError: OracleXML
I already installed xdk.
May 20, 2004 - 8:14 pm UTC
what's your classpath set to.
How to Seperate Concat Values
MSU, September 13, 2004 - 9:48 am UTC
Hi Tom and Sean,
SQL> desc order_formats
Name Null? Type
ORDER_ID NOT NULL NUMBER(18)
ORDER_XML NOT NULL SYS.XMLTYPE
Here is a sample query
select order_xml from order_formats where order_id=2055169;
And the result is this
<cXML timestamp="2004-09-06T11:05::13">
<Request>
<OrderRequest>
<ItemOut quantity="12" lineNumber="9">
<ItemID> <SupplierPartID>054054</SupplierPartID>
</ItemID>
</ItemOut>
<ItemOut quantity="10" lineNumber="10">
<ItemID>
<SupplierPartID>30054054</SupplierPartID>
</ItemID>
</ItemOut>
</OrderRequest>
</Request>
</cXML>
When I write a select query as
SELECT
order_id,
formats.order_xml.extract('/cXML/Request/OrderRequest/ItemOut/ItemID/SupplierPartID').getStringVal() SupplierID
FROM
ORDER_FORMATS formats
WHERE formats.order_id=2055169
I get the result as
ORDER_ID SUPPLIERID
---------- -----------------------------------------
2055169 <SupplierPartID>054054</SupplierPartID>
<SupplierPartID>30054054</SupplierPartID>
When I use text() in the query as mentioned below
SELECT
order_id,
formats.order_xml.extract('/cXML/Request/OrderRequest/ItemOut/ItemID/SupplierPartID/text()').getStringVal() SupplierID
FROM
ORDER_FORMATS formats
WHERE formats.order_id=2055169
Both the values inside the tag get concat
ORDER_ID SUPPLIERID
---------- ----------------
2055169 05405430054054
which I dont want. I want the result to be 2 numbers which are comma seperated. How to achieve the same. Thanking you in advance.
September 13, 2004 - 11:24 am UTC
select order_id || ',' || formats.order_xml.extract( ......
Comma seperated Values - Corrected Query
MSU, September 14, 2004 - 2:32 am UTC
Hi Tom,
At the outset my apologies for an ambiguous query posted last time,which I have corrected while posting this one.
In my XML I have more than one tag which are having the same name. Suppose I want to extract them all with a comma seperating them how do I do that.
In the sample which I had given I have 2 SupplierPartID.
When I write a query without using text() I get the values along with the tags.
SELECT
formats.order_xml.extract('//SupplierPartID').getString
FROM
ORDER_FORMATS formats
WHERE formats.order_id=2055169
The answer is as follows
SUPPLIERID
-----------------------------------------
<SupplierPartID>054054</SupplierPartID>
<SupplierPartID>30054054</SupplierPartID>
When I rewrite the same query with the text()
SELECT
formats.order_xml.extract
('//SupplierPartID/text()').getStringVal() SupplierID
FROM
ORDER_FORMATS formats
WHERE formats.order_id=2055169
The answer is like the one below.
SUPPLIERID
---------------
05405430054054
Both the values with the same tag - <SupplierPartID> get concat. I want these two values namely 054054 AND 30054054 to be comma seperated. How to achieve the same. Thanking you in anticipation.
September 14, 2004 - 6:46 pm UTC
I asked Sean, my XML guy, to take a look at this and here's what he had to say:
--
hi MSU,
This is pretty easy to do, you have a couple of options. First, you can use standard XSLT to do this inside the database. The XMLTYPE datatype has a member method (function) called TRANSFORM that will allow you to use any XSL stylesheet on your XML. If you google XSLT comma separated values, you'll find LOTS of stylesheets out there to help you write those.
You can also use DOM inside the database. So for instance, I might use the following code snippet to get a DOM document, get a list of DOM nodes, iterate over those nodes, and concatenate the values into a CSV that gets returned in a function:
----------------
SQL> create table t ( order_xml sys.xmltype );
Table created.
SQL> insert into t values ( xmltype(
2 '<x><SupplierPartID>123</SupplierPartID>
3 <SupplierPartID>456</SupplierPartID>
4 <SupplierPartID>789</SupplierPartID>
5 <SupplierPartID>abc</SupplierPartID>
6 <SupplierPartID>def</SupplierPartID>
7 </x>') );
1 row created.
SQL> create or replace function supplierList( p_xml XMLType ) return varchar2
2 is
3 l_supplier dbms_xmldom.DOMNode;
4 l_supplierElts dbms_xmldom.DOMNodeList;
5 l_supplierCnt pls_integer;
6 l_curSupplier dbms_xmldom.DOMNode;
7 l_csv clob;
8 l_val varchar2(100);
9 begin
10 l_supplier := dbms_xmldom.makeNode(dbms_xmldom.newDOMDocument(p_xml));
11 l_supplierElts := dbms_xslprocessor.selectNodes(l_supplier,'/x/SupplierPa
12 l_supplierCnt := dbms_xmldom.getLength(l_supplierElts);
13
14 for pos in 1..l_supplierCnt loop
15 l_curSupplier := dbms_xmldom.item(l_supplierElts,pos-1);
16 dbms_xslprocessor.valueOf(l_curSupplier,'text()',l_val);
17 l_csv := l_csv || l_val;
18 if pos <> l_supplierCnt then l_csv := l_csv || ','; end if;
19 end loop;
20 return l_csv;
21 end;
22 /
Function created.
SQL> select supplierList(order_xml)
2 from t
3 /
SUPPLIERLIST(ORDER_XML)
-----------------------------
123,456,789,abc,def
Hope that helps!
Error occurred in XML processing
MSU, September 15, 2004 - 9:20 am UTC
Hi Tom And Sean,
At the ouset thankyou very much for such a wonderful website.The DOM and XSLT methods for my above mentioned problem were really very useful to me. Since I am using a database with sys.xml type for the first time. I come across different types of errors / doubts every now and then. Today I came across one such. Please do have a look at the sample code below.
SQL> create table t ( order_xml sys.xmltype );
Table created.
SQL> desc t
Name Null? Type
ORDER_XML SYS.XMLTYPE
SQL> ed
Wrote file afiedt.buf
1 insert into t values ( SYS.XMLType.createXML('<?xml version="1.0" ?>
2 <ItemOut>
3 <ItemID>
4 <Description xml:lang="en"> SMOOTH PAPER 123 </Description>
5 <SupplierPartID>123</SupplierPartID>
6 </ItemID>
7* </ItemOut>'))
SQL> /
1 row created.
SQL> select * from t;
ORDER_XML
---------
<ItemOut>
<ItemID>
<Description xml:lang="en">SMOOTH PAPER 123 </Description>
<SupplierPartID>123</SupplierPartID>
</ItemID>
</ItemOut>
SELECT
T1.extract('/ItemOut/ItemID/SupplierPartID/text()').getStringVal()
SupplierID
FROM t,
TABLE(XMLSEQUENCE(EXTRACT(order_xml,'//ItemOut'))) T1
SELECT
*
ERROR at line 1:
ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML processing
LPX-00233: namespace prefixes starting with "xml" are reserved
Error at line 3
ORA-06512: at "SYS.XMLSEQ_IMP_T", line 7
ORA-06512: at "SYS.XMLSEQ_IMP_T", line 7
At the same time if my <Description> is plain (Without any XML:lang="en") The same query runs perfectly. Which I have given below
SQL> delete from t;
1 row deleted.
SQL> ed
Wrote file afiedt.buf
1 insert into t values ( SYS.XMLType.createXML('<?xml version="1.0" ?>
2 <ItemOut>
3 <ItemID>
4 <Description> SMOOTH PAPER 123 </Description>
5 <SupplierPartID>123</SupplierPartID>
6 </ItemID>
7* </ItemOut>'))
8 /
1 row created.
SQL> select * from t;
ORDER_XML
---------
<ItemOut>
<ItemID>
<Description>SMOOTH PAPER 123 </Description>
<SupplierPartID>123</SupplierPartID>
</ItemID>
</ItemOut>
SQL> ed
Wrote file afiedt.buf
1 SELECT
2 T1.extract('/ItemOut/ItemID/SupplierPartID/text()').getStringVal()
3 SupplierID
4 FROM t,
5* TABLE(XMLSEQUENCE(EXTRACT(order_xml,'//ItemOut'))) T1
SQL> /
SUPPLIERID
-----------
123
I wish to know what exactly is the error and how to overcome this. Thanking you in anticipation.
September 15, 2004 - 5:20 pm UTC
Sean Dillon here...
--
Well, you actually have a couple of problems. First of all, XML is a reserved namespace. You can't use it for your own custom namespace declaration. You can check into the W3C XML standard for reserved namespaces (not sure of others but I'm sure if I say there aren't any there will be), but clearly XML is one of them.
Second, even if you used a non-reserved word for your namespace, your XML document isn't well-formed as there is no namespace declaration. Consider...
SQL> create table t ( order_xml sys.xmltype );
Table created.
-- YOUR PROBLEM, YOU CAN'T USE THE XML NAMESPACE EVEN IF YOU DECLARE IT:
SQL> insert into t values ( SYS.XMLType.createXML('<?xml version="1.0" ?>
2 <ItemOut xmlns:xml="
http://www.oracle.com" >
3 <ItemID>
4 <Description xml:lang="en"> SMOOTH PAPER 123 </Description>
5 <SupplierPartID>123</SupplierPartID>
6 </ItemID>
7 </ItemOut>'));
insert into t values ( SYS.XMLType.createXML('<?xml version="1.0" ?>
*
ERROR at line 1:
ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML processing
LPX-00233: namespace prefixes starting with "xml" are reserved
Error at line 2
ORA-06512: at "SYS.XMLTYPE", line 54
ORA-06512: at line 1
-- THIS SQL INSERT SHOWS THE NEXT PROBLEM, NOT USING A RESERVED WORD (XSI) BUT
-- NOT DECLARING THE XSI NAMESPACE:
SQL> insert into t values ( SYS.XMLType.createXML('<?xml version="1.0" ?>
2 <ItemOut>
3 <ItemID>
4 <Description xsi:lang="en"> SMOOTH PAPER 123 </Description>
5 <SupplierPartID>123</SupplierPartID>
6 </ItemID>
7 </ItemOut>'))
8 /
insert into t values ( SYS.XMLType.createXML('<?xml version="1.0" ?>
*
ERROR at line 1:
ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML processing
LPX-00234: namespace prefix "xsi" is not declared
Error at line 4
ORA-06512: at "SYS.XMLTYPE", line 54
ORA-06512: at line 1
-- HERE, WE DECLARE THE XSI NAMESPACE AND WE USE IT APPROPRIATELY, NO PROB:
SQL> insert into t values ( SYS.XMLType.createXML('<?xml version="1.0" ?>
2 <ItemOut xmlns:xsi="
http://www.oracle.com" >
3 <ItemID>
4 <Description xsi:lang="en"> SMOOTH PAPER 123 </Description>
5 <SupplierPartID>123</SupplierPartID>
6 </ItemID>
7 </ItemOut>'));
1 row created.
SQL> select * from t;
ORDER_XML
--------------------------------------------------------------------------------
<?xml version="1.0" ?>
<ItemOut xmlns:xsi="
http://www.oracle.com" >
<ItemID>
...etc...
Hope that helps!
_Sean Dillon_
XML Output
Sudip Sarkar, September 15, 2004 - 10:57 am UTC
Hi Tom,
I have a requirement where I have to take out data from two tables (Master and Detail), the output needs to be in XML format.
The attributes from the detail table will be repeating, Is it possible to produce this kind of output using dbms_xmlquery package?
Order Master Table
Order_ID Order_Date
1 12/10/2004
2 11/10/2004
Order Detail Table
Order_ID Item_number QTY
1 ITM01 4
1 ITM02 1
1 ITM03 3
1 ITM04 5
The following is the output need
Order_Id
Order_date
Item_number -- this is multiple for each order
QTY -- this is multiple for each order
Thanks
September 15, 2004 - 11:37 am UTC
XMLTYPE()
A reader, September 15, 2004 - 1:50 pm UTC
FYI. To the user above who was hitting the XMLTYPE() response when trying to run a SQLX statement.. It's the version of SQL*Plus you use.
9204 returns the goods fine.
901x doesn't.
Assigning Value Inside an Tag to a variable
MSU, September 22, 2004 - 9:20 am UTC
Hello Tom,
Thanks a million for such a wonderful site. Tom please do have look at the folowing
SQL> create table my_table ( x int, y sys.xmltype );
Table created.
SQL> insert into my_table values ( 1, xmltype( '<A>Aa<B>Bb<C>ABC</C></B></A>'));
1 row created.
SQL> select msu.y.extract('/A/B/C/text()').getstringval() from my_table msu;
MSU.Y.EXTRACT('/A/B/C/TEXT()').GETSTRINGVAL()
--------------------------------------------------------------------------------
ABC
SQL> ed
Wrote file afiedt.buf
1 DECLARE
2 v_val SYS.XMLTYPE;
3 cursor c_table_update is
4 select msu.y.extract('/A/B/C/text()').getstringval() val from my_table msu;
5 BEGIN
6 open c_table_update;
7 loop
8 fetch c_table_update into v_val ;
9 exit when c_table_update%notfound;
10 dbms_output.put_line(to_char(v_val));
11 END LOOP;
12 CLOSE c_table_update;
13* END;
SQL> /
fetch c_table_update into v_val ;
*
ERROR at line 8:
ORA-06550: line 8, column 30:
PLS-00386: type mismatch found at 'V_VAL' between FETCH cursor and INTO variables
ORA-06550: line 8, column 4:
PL/SQL: SQL Statement ignored
ORA-06550: line 10, column 25:
PLS-00306: wrong number or types of arguments in call to 'TO_CHAR'
ORA-06550: line 10, column 4:
PL/SQL: Statement ignored
(1) What is the meaning of the 2 ORACLE Error messages which I am getting and more importantly why am I getting this error inspite of declaring the variable as sys.xmltype.
(2) Where am I going wrong ?
(3) How to assign the value of the XML node which has been extracted into a variable. Do let me know. Thanking you in anticipation
September 22, 2004 - 10:08 am UTC
1) means the data type you are fetching into doesn't match that which you are fetching and cannot be converted implicitly.
It is because you made it xmltype, that it is failing. Here is what I do to see "what are the types" really quick:
ops$tkyte@ORA9IR2> create or replace view vw
2 as
3 select msu.y.extract('/A/B/C/text()').getstringval() data from my_table msu;
View created.
ops$tkyte@ORA9IR2> desc vw
Name Null? Type
---------------------------------------- -------- ----------------------------
DATA VARCHAR2(4000)
getStringval returns a STRING -- not an xmltype!
I would just code:
for x in ( your query here )
loop
use x.attribute ....
end loop;
explicit cursors are a pain in the butt.
"Error occurred in XML processing - II"
MSU, September 23, 2004 - 9:10 am UTC
Hi Tom and Sean,
At the very outset thanks a million for such a wonderful site. Thanks again for the detailed answer to my query "Error occurred in XML processing"
Please do have a look at the below mentioned code
SQL> create table t ( order_xml sys.xmltype );
Table created.
SQL> desc t
Name Null? Type
ORDER_XML SYS.XMLTYPE
SQL> ed
Wrote file afiedt.buf
1 insert into t values ( SYS.XMLType.createXML('<?xml version="1.0" ?>
2 <ItemOut>
3 <ItemID>
4 <Description xml:lang="en"> SMOOTH PAPER 123 </Description>
5 <SupplierPartID>123</SupplierPartID>
6 </ItemID>
7* </ItemOut>'))
SQL> /
1 row created.
SQL> select * from t;
ORDER_XML
---------
<ItemOut>
<ItemID>
<Description xml:lang="en">SMOOTH PAPER 123 </Description>
<SupplierPartID>123</SupplierPartID>
</ItemID>
</ItemOut>
SELECT
T1.extract('/ItemOut/ItemID/SupplierPartID/text()').getStringVal()
SupplierID
FROM t,
TABLE(XMLSEQUENCE(EXTRACT(order_xml,'//ItemOut'))) T1
SELECT
*
ERROR at line 1:
ORA-31011: XML parsing failed
ORA-19202: Error occurred in XML processing
LPX-00233: namespace prefixes starting with "xml" are reserved
Error at line 3
ORA-06512: at "SYS.XMLSEQ_IMP_T", line 7
ORA-06512: at "SYS.XMLSEQ_IMP_T", line 7
To overcome this problem you had suggested me to use XSI namespace instead of XML Namespace. But I have a situation where in I have about 100K entries in my Table ( In turn 100K XML scripts) which are having XML Namespace.
Moreover I have to work(query) the scripts which are in the above mentioned format - Having XML Namespace. I am not allowed to change the scripts. Is there anyway I can query such scripts having XML namespace and get an answer ?
If the above mentioned is impossible and also assuming that I am allowed to change the name space(From XML to XSI) in my XML scripts how to proceed to achieve the same.
Thanking you in anticipation.
XMLType and Embedded pdf
Govind Agnihotri, October 11, 2004 - 2:25 pm UTC
I have a XML with a embedded .pdf ( Base64 encoded) in a Document Cdata tag?
I could get all the other tags using Xpath expressions, How do your get the pdf section and store it in a blob. When I get Stringval '<DOCUMENT>', [CDATA[', ']]></DOCUMENT> are a part of the string.
The pdf viewer complains the document contains non-base64 string?
Do you have any API's to extract CDATA sections in XMLtype?
Thanks in advance,
Govind.
Who is eating my CRLF's??!!
Nemec, February 01, 2005 - 7:29 am UTC
I've a very simple problem, but I can't find the solution. So please help:
Using xmlelement I get
SQL> SELECT XMLELEMENT("Emp", XMLELEMENT("name", 'Abbbbb'),
XMLELEMENT ( "hiredate", '01011900')) AS "result"
FROM dual 2 3 ;
result
--------------------------------------------------------------------------------
<Emp><name>Abbbbb</name><hiredate>01011900</hiredate></Emp>
SQL>
I'd like to get somthing like that (examples in manuals are in that form)
<Emp>
<name>Abbbbb</name>
<hiredate>01011900</hiredate>
</Emp>
Other question. How could I generate the <?xml version="1.0"?> line on the top of the document?
Thanks
Jaromir
February 01, 2005 - 9:51 am UTC
SQL> select xmltype.createxml('<?xml version="1.0"?>' ||
2 xmlelement("Emp",
3 xmlforest('Abbbbb' as "name",
4 '01011900' as "hiredate")
5 )
6 )
7 from dual
8 /
XMLTYPE.CREATEXML('<?XMLVERSION="1.0"?>'||XMLELEMENT("EMP",XMLFOREST('ABBBBB'AS"
--------------------------------------------------------------------------------
<?xml version="1.0"?><Emp><name>Abbbbb</name><hiredate>01011900</hiredate></Emp>
SQL*Plus formats XML
Tak Tang, February 01, 2005 - 11:41 am UTC
In response to Nemec/Jaromir from Tabor . . .
SQL*Plus is the thing that formats the XMLTYPE. In the past, my XML came out as a serialised string (as your's has), but it is currently comming out nicely formatted (like the manuals). I'm not sure whether this is due to which version of SQL*Plus I am running (SQL*Plus: Release 9.2.0.1.0 - Production), or if it is a SETting.
'SQL*Plus: Release 8.0.6.0.0 - Production' crashes with XMLTYPE, and a popular third party tool returns '(ORAXML)'.
Tak
thank you
mar, February 03, 2005 - 7:53 pm UTC
thank you for the good helps that you give it to the students like me .
i wish you luck .
for give me for that bad lunguage.
convert to flat cvs file first, and then convert to xml for better performance
Jim, February 15, 2005 - 1:28 am UTC
If large tables with a lot of data, then tools that allow quickly extract tables into csv files and generate XML then will be useful for that purpose.
I know FastReader can convert large Oracle tables into xml files in efficient way. Probably some other tools do similar.
wisdomforce Fastreader that I mentioned can be found at www.wisdomforce.com
relational query from xmltype column
Nilanjan Ray, February 16, 2005 - 8:05 am UTC
I have created the following table:
CREATE TABLE test_xml_tab(
poid number,
pDoc XMLTYPE);
created directory :
CREATE DIRECTORY xmlfiles AS '/appl/oracle/xmldata';
created function
create or replace function fileToClob(fname varchar2) return clob is
fclob clob;
theBFile BFILE;
begin
dbms_lob.createtemporary(fclob,false,DBMS_LOB.SESSION);
theBFile := BFileName('XMLFILES',fname);
dbms_lob.fileOpen(theBFile);
dbms_lob.loadFromFile(fclob,
theBFile,
dbms_lob.getLength(theBFile));
dbms_lob.fileClose(theBFile);
return fclob;
end;
/
loaded xml:
INSERT INTO test_xml_tab VALUES (100, XMLType(fileToClob('txml.xml')));
sample data:
- <Response>
- <ACResponse>
- <CommonDataResponse>
- <CommonMandatoryResponse HcsTcsInd="T" LangInd="00" MessageType="A" TzCode="705" Version="2">
<MerchantID>123456789012</MerchantID>
<TerminalID>001</TerminalID>
<TxRefNum>128E6C6A4FC6D4119A3700D0B706C51EE26DF570</TxRefNum>
<TxRefIdx>0</TxRefIdx>
<OrderNumber>1234567890123456</OrderNumber>
<RespTime>10012001120003</RespTime>
<ProcStatus>0</ProcStatus>
<ApprovalStatus>1</ApprovalStatus>
- <ResponseCodes>
<AuthCode>tntC09</AuthCode>
<RespCode>00</RespCode>
<HostRespCode>00</HostRespCode>
<CVV2RespCode>M</CVV2RespCode>
<HostCVV2RespCode>M</HostCVV2RespCode>
<AVSRespCode>H</AVSRespCode>
<HostAVSRespCode>Y</HostAVSRespCode>
</ResponseCodes>
- <ResponseCodes>
<AuthCode>tntC091</AuthCode>
<RespCode>00</RespCode>
<HostRespCode>00</HostRespCode>
<CVV2RespCode>M</CVV2RespCode>
<HostCVV2RespCode>M</HostCVV2RespCode>
<AVSRespCode>H</AVSRespCode>
<HostAVSRespCode>Y</HostAVSRespCode>
</ResponseCodes>
- <ResponseCodes>
<AuthCode>tntC092</AuthCode>
<RespCode>00</RespCode>
<HostRespCode>00</HostRespCode>
<CVV2RespCode>M</CVV2RespCode>
<HostCVV2RespCode>M</HostCVV2RespCode>
<AVSRespCode>H</AVSRespCode>
<HostAVSRespCode>Y</HostAVSRespCode>
</ResponseCodes>
</CommonMandatoryResponse>
- <CommonOptionalResponse>
<AccountNum>4012888888881</AccountNum>
<RespDate>010801</RespDate>
<CardType>VI</CardType>
<ExpDate>200512</ExpDate>
<CurrencyCd>840</CurrencyCd>
</CommonOptionalResponse>
</CommonDataResponse>
- <AuthResponse>
<AuthMandatoryResponse />
- <AuthOptionalResponse>
<POSEntryMode>01</POSEntryMode>
- <MISCData>
<ActualRespCd>00</ActualRespCd>
</MISCData>
- <NetworkData>
<AuthNetwkID>01</AuthNetwkID>
</NetworkData>
- <VisaCard>
- <CPSData>
<AuthCharInd>V</AuthCharInd>
<ValidationCd>JU9E</ValidationCd>
</CPSData>
<AuthSource AuthSrc="5" />
<VisaCommCard VCC="S" />
</VisaCard>
</AuthOptionalResponse>
</AuthResponse>
</ACResponse>
</Response>
My question is, how do I use a select statement to retrive all the records in relational format from the xmltype column?
Regards
February 16, 2005 - 10:02 am UTC
I asked Sean Dillon to take a look at this, here's what he had to say:
--
Fortunately, we document stuff like this. I suggest you look at these URL's for more information on querying XML data:
XML DB Developer's Guide : </code>
http://docs.oracle.com/docs/cd/B14117_01/appdev.101/b10790/toc.htm (See Chapter 3 Using XML DB, specifically the section on "Querying XML Content Stored in Oracle XML DB". I recommend anybody using XML DB read through this entire document, it's incredibly helpful in understanding how XML DB works and how to employ it properly.)
XML DB Technology Center on OTN :
http://www.oracle.com/tech/xml
XML DB sample code (download/install/run the "Oracle9i R2 XML DB Demonstration", it'll help you tremendously):
http://www.oracle.com/technology/sample_code/tech/xml/xmldb/index.html <code>
Hope that helps,
_smd_
Sean Dillon
relational query from xmltype column-extractvalue(..)
Nilanjan Ray, February 17, 2005 - 6:11 am UTC
Thanks Tom/Sean,
I was able to do it by going through Oracle doc. Amazing stuff!!! I have been using Oracle since ver 7. 9i is awesome, 10g is definitely more !!!!!
One simple question though...
Using the following data.
<?xml version = '1.0' encoding = 'UTF-8'?>
<ROWSET>
<ROW>
<START_TM>284659</START_TM>
<EVENT_NM><![CDATA[The People'S Book Of Records # 1]]></EVENT_NM>
<MODIFY_BY>SYSTEM</MODIFY_BY>
</ROW>
<ROW>
<START_TM>284659</START_TM>
<EVENT_NM><![CDATA[The People'S Book Of Records # 1]]></EVENT_NM>
<MODIFY_BY>SYSTEM</MODIFY_BY>
</ROW>
<ROWSET>
Using the foloowing SQL I can extract the value of one column:
SELECT extractValue(value(t),'/START_TM') start_tm
FROM XMLTABLE X,
TABLE (
xmlsequence ( extract(value(X),'/ROWSET/ROW/START_TM') )
) t
I would like to select all the values of START_TM,EVENT_NM and MODIFY_BY in a single statement in column format.
START_TM EVENT_NM MODIFY_BY
-------- -------- ---------
284659 The People'S Book Of Records SYSTEM
284660 The Joy # 1 SYSTEM
Please suggest.
Regards
March 04, 2005 - 9:53 am UTC
I asked Sean Dillon to take a look at this, here's what he had to say:
--
You just need to select the XMLSEQUENCE at a higher level in the node tree, and specify the sub-elements in your extractvalue statements:
SQL> create table xmltest of xmltype
2 /
Table created.
SQL> insert into xmltest values(
2 xmltype(
3 '<?xml version = "1.0" encoding = "UTF-8"?>
4 <ROWSET>
5 <ROW>
6 <START_TM>284659</START_TM>
7 <EVENT_NM><![CDATA[The People''s Book Of Records # 1]]></EVENT_NM>
8 <MODIFY_BY>SYSTEM</MODIFY_BY>
9 </ROW>
10 <ROW>
11 <START_TM>284659</START_TM>
12 <EVENT_NM><![CDATA[The People''s Book Of Records # 1]]></EVENT_NM>
13 <MODIFY_BY>SYSTEM</MODIFY_BY>
14 </ROW>
15 </ROWSET>'))
16 /
1 row created.
SQL> col start_tm for a10
SQL> col event_nm for a40
SQL> col modify_by for a20
SQL> select extractValue(value(t),'/ROW/START_TM') start_tm,
2 extractValue(value(t),'/ROW/EVENT_NM') event_nm,
3 extractValue(value(t),'/ROW/MODIFY_BY') modify_by
4 from xmltest x,
5 table ( xmlsequence ( extract(value(x),'/ROWSET/ROW') ) ) t
6 /
START_TM EVENT_NM MODIFY_BY
---------- ---------------------------------------- --------------------
284659 The People's Book Of Records # 1 SYSTEM
284659 The People's Book Of Records # 1 SYSTEM
Where clause in XML query?
Tony, February 25, 2005 - 10:13 am UTC
Tom,
What I want out is basically
<ProductList>
<Product>
<Main></Main>
<Modified></Modified>
<EnduranceList>
<Endurance>
<EnduranceName></EnduranceName>
<EnduranceSpec></EnduranceSpec>
<EnduranceRoll></EnduranceRoll>
<Endurance/>
<Endurance>
<EnduranceName></EnduranceName>
<EnduranceSpec></EnduranceSpec>
<EnduranceRoll></EnduranceRoll>
<Endurance/>
<Endurance>
<EnduranceName></EnduranceName>
<EnduranceSpec></EnduranceSpec>
<EnduranceRoll></EnduranceRoll>
<Endurance/>
<Endurance>
<EnduranceName></EnduranceName>
<EnduranceSpec></EnduranceSpec>
<EnduranceRoll></EnduranceRoll>
<Endurance/>
<Endurance>
<EnduranceName></EnduranceName>
<EnduranceSpec></EnduranceSpec>
<EnduranceRoll></EnduranceRoll>
<Endurance/>
</EnduranceList>
</Product>
</ProductList>
With values inbetween the tags.
And this is what I use to generate it:
select xmlelement("ProductList",
(SELECT xmlagg(xmlelement ("Product", xmlforest (p.main as "Main", p.modified
as "Modified"),
xmlelement ("EnduranceList",
(SELECT xmlagg(xmlelement("Endurance", xmlforest (
DECODE (q,
1, 'Main',
2, 'Sub',
3, 'Cat',
4, END01,
5, END02
) AS "EnduranceName",
DECODE (s,
1, Main,
2, Sub,
3, Cat,
4, "Value01",
5, "Value02"
) AS "EnduranceSpec",
DECODE (r,
1, null,
2, null,
3, null,
4, UNIT_END01,
5, UNIT_END02
) AS "EnduranceRoll")))
FROM (SELECT mcah.END01, mcah.UNIT_END01, mcah.END02,
mcah.UNIT_END02,
mcpd.Sub, mcpd.Cat, mcpd.Main
mcpd.END01 as "Value01", mcpd.END02 as "Value02"
FROM enduranceDiv mcah, enduranceMain mcpd
WHERE mcpd.sub = mcah.sub
AND mcpd.cat = mcah.cat
),
(SELECT 1 q, 1 r, 1 s
FROM DUAL
UNION ALL
SELECT 2, 2, 2
FROM DUAL
UNION ALL
SELECT 3, 3, 3
FROM DUAL
UNION ALL
SELECT 4, 4, 4
FROM DUAL
UNION ALL
SELECT 5, 5, 5
FROM DUAL) WHERE main = p.main ---> AND
"EnduranceName" IS NOT NULL <---
)
)))
from enduranceMain p where p.main = 'Product1' )
)
from dual
The problem is when I have null values for the 5 values in the decode function
I'll be left with a <Endurance />
Which I don't want - that's why I want to write something similar to what I've
added to the where clause (EnduranceName is not null). When EnduranceName is
null then all the other values are also null for sure.
Do you have some simple way in mind of easily resolve this?
Brgds,
/Tony
March 04, 2005 - 10:16 am UTC
I asked Sean Dillon, our local XML guy, to take a look at this, here's what he had to say:
--
Tony,
I'm a little confused with what you're trying to do, but there are a couple of bits of advice I can offer.
1. If you want to force an element to be in the result set of an SQLXML query, whether it has a value or not, use XMLELEMENT as your query operator. If the result value for that column is null, you'll get a self-closed tag in your result (i.e., <NULLCOLUMN/>).
2. If you want to only show an element if it has a value, use the XMLFOREST SQLXML query operator. This will remove elements from the resulting document if the result value for that column is null.
3. If you want to selectively query columns in your query based on the value of EnduranceName (or some condition), use a plain ole CASE statement. You can embed the other nodes you want queried inside the case statement's based on satisfying some condition, or alternatively choose to select no subnodes if the condition isn't met (etc..).
How to generate XML files in client side(FORM 10g)
AS, May 16, 2005 - 5:36 pm UTC
Hi,
DB: 9iR2, form ORACLE 10g
1. Would you mind give me an example on how to write XML files on client side (and store them there), not server side;
2. Related to question 1, we want to generate data files in EXCEL format in 10g form on client side, but don't want your SLK file format anymore. So we want to first generate the data file in XML format, and then try to open it by Office 2003, is it a good way and how to do that if it is?
3. Do you have any inputs on that issue please?
Thanks for your time.
May 16, 2005 - 5:56 pm UTC
1) retrieve xml from database into client application written in language of your choice and write to file system...
2) it is not "my" sylk file format, it is the industries....
but you would do precisely the same thing you would for sylk. if you want to do this on the client, write code on client in language of choice
3) the more you centralize and the less you clientize the better you'll be in the long run...
Deleting from a table of xmltype
Claude, January 16, 2006 - 4:49 pm UTC
Hi Tom/Sean,
I have hopefully a simple question for you that I can't figure out...
I'm creating a simple xmltype table with no key. The commands that I use to create and populate it are shown. Later I want to delete a row based on a key.
create table items of xmltype;
insert into items
values (xmltype.createxml(
'<item>'||
'<id>123</id>'||
'<name>smooth paper</name>'||
'</item>'));
insert into items
values (xmltype.createxml(
'<item>'||
'<id>456</id>'||
'<name>noisy printer</name>'||
'</item>'));
commit;
Now I want to delete the record with the ID of 123. How do I do that? ie...
delete from items i
where extract(value(i), '/items/id') = '123'
/
but without the ORA-22950 error.
Thanks
XML Version tag revisited
Reed Hammond, February 09, 2006 - 1:42 pm UTC
Hi Tom,
I am trying to add the <?xml version="1.0"?> tag to the beginning of my xml output. I noticed a followup on this thread that gave me something to try so I added
mltype.createxml('<?xml version="1.0"?>' ||
to a query I had working, right after the select with a close parenthesis before the from statement, but now I am getting the error ORA-19011: Character string buffer too small.
I was expecting the output to generate in a clob.Is the database converting the output to something other than a clob before it returns? Is there something else I should be doing?
Thanks
February 10, 2006 - 11:30 am UTC
if you concatenated a string to a string, you get a string...
you might have to convert to let it know what you mean:
ops$tkyte@ORA10GR2> create table t ( x clob );
Table created.
ops$tkyte@ORA10GR2>
ops$tkyte@ORA10GR2> declare
2 l_str varchar2(4000) := rpad('*',4000,'*');
3 begin
4 insert into t values ( 'abc' || l_str );
5 end;
6 /
declare
*
ERROR at line 1:
ORA-01489: result of string concatenation is too long
ORA-06512: at line 4
ops$tkyte@ORA10GR2> declare
2 l_str varchar2(4000) := rpad('*',4000,'*');
3 begin
4 insert into t values ( 'abc' || to_clob(l_str) );
5 end;
6 /
PL/SQL procedure successfully completed.
Using xmlschema as object relational
Claude, March 02, 2006 - 3:44 pm UTC
Hi Tom,
I tried to create a table with schema-based storage but didn't get very far.
SQL> CREATE TABLE students(student_id VARCHAR2(15) NOT NULL,
student_xml XMLType NOT NULL)
XMLTYPE COLUMN student_xml STORE AS OBJECT RELATIONAL
XMLSCHEMA "students.xsd"
ELEMENT "student";
CREATE TABLE students (student_id VARCHAR2(15) NOT NULL,
*
ERROR at line 1:
ORA-00902: invalid datatype
Here is the register-schema command I'm using:
DBMS_XMLSCHEMA.REGISTERSCHEMA(
schemaurl => 'students.xsd',
schemadoc => '<xsd:schema xmlns:xsd="
http://www.w3.org/2001/XMLSchema" >
<xsd:element name="student">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="change_date" type="xsd:string"/>
<xsd:element name="enrollment_term">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="semester" type="xsd:string"/>
<xsd:element name="status" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="person_name" type="xsd:string"/>
<xsd:attribute name="ssn" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>',
local => TRUE,
gentypes => TRUE,
gentables => FALSE
);
Metalink says to use the clause "store as clob". That gets rid of the error, but loses the ability to use schema-based storage (and B*Tree indexes, etc). What am I missing?
Thanks
March 03, 2006 - 7:48 am UTC
ops$tkyte@ORA10GR2> CREATE TABLE students(student_id VARCHAR2(15) NOT NULL,
2 student_xml XMLType NOT NULL)
3 XMLTYPE COLUMN student_xml STORE AS OBJECT RELATIONAL
4 XMLSCHEMA "students.xsd"
5 ELEMENT "student";
Table created.
version?
ops$tkyte@ORA10GR2> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
Using xmlschema as object relational
Claude, March 03, 2006 - 9:15 am UTC
Here's the version I'm using:
BANNER
---------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.5.0 - 64bit Production
PL/SQL Release 9.2.0.5.0 - Production
CORE 9.2.0.6.0 Production
TNS for Solaris: Version 9.2.0.5.0 - Production
NLSRTL Version 9.2.0.5.0 - Production
March 03, 2006 - 12:56 pm UTC
seems more like something is wrong with your installation perhaps, please work with support:
ops$tkyte@ORA9IR2> begin
2 DBMS_XMLSCHEMA.REGISTERSCHEMA(
3 schemaurl => 'students.xsd',
4 schemadoc => '<xsd:schema xmlns:xsd="
http://www.w3.org/2001/XMLSchema" >
5 <xsd:element name="student">
6 <xsd:complexType>
7 <xsd:sequence>
8 <xsd:element name="change_date" type="xsd:string"/>
9 <xsd:element name="enrollment_term">
10 <xsd:complexType>
11 <xsd:sequence>
12 <xsd:element name="semester" type="xsd:string"/>
13 <xsd:element name="status" type="xsd:string"/>
14 </xsd:sequence>
15 </xsd:complexType>
16 </xsd:element>
17 </xsd:sequence>
18 <xsd:attribute name="id" type="xsd:string"/>
19 <xsd:attribute name="person_name" type="xsd:string"/>
20 <xsd:attribute name="ssn" type="xsd:string"/>
21 </xsd:complexType>
22 </xsd:element>
23 </xsd:schema>',
24 local => TRUE,
25 gentypes => TRUE,
26 gentables => FALSE
27 );
28 end;
29 /
PL/SQL procedure successfully completed.
ops$tkyte@ORA9IR2> CREATE TABLE students(student_id VARCHAR2(15) NOT NULL,
2 student_xml XMLType NOT NULL)
3 XMLTYPE COLUMN student_xml STORE AS OBJECT RELATIONAL
4 XMLSCHEMA "students.xsd"
5 ELEMENT "student";
Table created.
ops$tkyte@ORA9IR2> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.5.0 - Production
PL/SQL Release 9.2.0.5.0 - Production
CORE 9.2.0.6.0 Production
TNS for Linux: Version 9.2.0.5.0 - Production
NLSRTL Version 9.2.0.5.0 - Production
Using xmlschema as object relational
Claude, March 03, 2006 - 4:49 pm UTC
That example works for me now too. The example I put together I touched up to remove the confidential information and I guess I inadvertantly fixed it in the process. :-[
This gives me something to work on for now. Thanks for your quick responses.
A reader, March 26, 2006 - 12:26 pm UTC
Hi Tom,
We have xsd:dateTime type with the foramt in the xsd. It's really giving me hard time. It is expecting value in following format 2006-02-16T11:14:26
How can I get this field value in oracle.
I tried following but it's giving me error...
XMLForest( sp_eim_key.nextval as "trans_id"
, TO_CHAR(a.last_upd,'YYYY-MM-DD"T"hh24:mi:SS') as "trans_date" <<<<<<<<<<<---------------------- ,'SADMIN' as "trans_creator"
,'MH' as "source_system"
, 'U' as "rec_type"
)
)
<xsd:element name="trans_date" nillable="false">
<xsd:simpleType>
<xsd:annotation>
<xsd:documentation>
Date the record was placed in the queue/drop location.
</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:dateTime">
<xsd:pattern value="\p{Nd}{4}-\p{Nd}{2}-\p{Nd}{2}T\p{Nd}{2}:\p{Nd}{2}:\p{Nd}{2}"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
P.S - I am generating the xml document using sqlx function and validating it againt the xsd. I have already registered the schema in the database.
Thanks
A reader, March 26, 2006 - 12:29 pm UTC
Forgot to mention one thing..
Just checked underlying db ojbects created by xbms_xmlschema.registerschema proocedure and found TIMESTAMP datatype created for "xsd:dateTime"
Xml Query Input
sagar, September 04, 2006 - 3:27 pm UTC
Hi Tom,
Is it possible to query the database using xml. My Sample XML Query will be some thing like
<Query>
<Select>All</Select>
<From>
<Tablename>emp</Tablename>
</From>
<WhereCondition>All</WhereCondition>
</Query>
Basically I am try to do (select * from emp);
Identical Attributes
A reader, February 08, 2007 - 9:27 am UTC
I have an XML file whcih resides on the FTP site
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cXML SYSTEM "
http://xml.cXML.org/schemas/cXML/1.2.011/Fulfill.dtd" >
<cXML timestamp="2007-02-06T01:21:26+00:00" xml:lang="en-US" payloadID="1170724886050.7621197.85262388@SEAAPP11">
<Header>
<From>
<Credential domain="DUNS">
<Identity>001903202</Identity>
</Credential>
</From>
<To>
<Credential domain="ZZ">
<Identity>ADPDS</Identity>
</Credential>
</To>
<Sender>
<Credential domain="DUNS">
<Identity>001903202</Identity>
</Credential>
<UserAgent>Hubspan Translation Services</UserAgent>
</Sender>
</Header>
<Request deploymentMode="test">
<ShipNoticeRequest>
<ShipNoticeHeader shipmentID="0800018638" noticeDate="2007-02-02T12:00:00-12:00" shipmentDate="2007-02-02T12:00:00-12:00" deliveryDate="2007-02-08T12:00:00-12:00">
<Contact role="shipFrom">
<Name xml:lang="en-US">GRAYBAR ELECTRIC CO</Name>
<PostalAddress>
<Street/>
<City>MINNEAPOLIS</City>
<State>MN</State>
<PostalCode>55406</PostalCode>
<Country isoCountryCode="US"/>
</PostalAddress>
</Contact>
<Contact role="shipTo">
<Name xml:lang="en-US">GROUP 1 BOB HOWARD A</Name>
<PostalAddress>
<Street>100 NORTH WEST POINTE BLVD</Street>
<City>ELK GROVE VILLAGE</City>
<State>IL</State>
<PostalCode>60007</PostalCode>
<Country isoCountryCode="US"/>
</PostalAddress>
</Contact>
</ShipNoticeHeader>
<ShipControl>
<CarrierIdentifier domain="companyName">4M UPS - GROUND</CarrierIdentifier>
<ShipmentIdentifier>0800018638</ShipmentIdentifier>
</ShipControl>
<ShipNoticePortion>
<OrderReference orderID="1141562">
<DocumentReference payloadID=""/>
</OrderReference>
<ShipNoticeItem quantity="5" lineNumber="000101">
<UnitOfMeasure>EA</UnitOfMeasure>
</ShipNoticeItem>
</ShipNoticePortion>
</ShipNoticeRequest>
</Request>
</cXML>
here i need to get values of attributes under <Contact role="shipTo"> attribute if you look at the above file we have <COntact role="xxxx"> twice now while using
v_xml_dom_det_info_list := xpath.SelectNodes( p_xml_dom_doc, 'cXML/Request/ShipNoticeRequest/ShipNoticeHeader/Contact' );
v_contact_shipto := xpath.valueof( v_xml_dom_det_info_list,'role');
how can i make sure v_contact_shipto gets "Shipto" value only.
Thanks,
Ark
A reader, December 08, 2011 - 11:08 am UTC
Hi Tom,
I have an XML document (file name = employee.txt) with the below XML :
<Employee>
<id>1234</id>
<Name>Shane</Name>
<Sal>12345</Salary>
<dept_id>45</dept_id>
<Address_details>abcdefgh</ Address_details >
</Employee>
1.I want to extract the above data and insert into 2 tables
a.Employee table (id,Name,Sal,dept_id)
b.Address table (id,Address_details)
2.Similary I want to generate the XML in the above format from the 2 tables . How can we do that ?
Could you please advise the best way to do these on Oracle 11g R2?
Thanks