Publishing of SQL data as XML
You can use the XMLElement(), XMLConcat(), XMLAgg(), and XMLAttributes() functions within an SQL expression to transform the results of a database query into XML.
select XMLElement('Parent', 'Parent Text');
<Parent>Parent Text</Parent>
XMLELEMENT
-----------
XML
(1 row)
select XMLSerialize(XMLElement('Parent', 'Parent Text'));
XMLSERIALIZE
------------------------------
<Parent>Parent Text</Parent>
(1 row)
select
XMLElement('Parent',
XMLElement('Child', 'Child text'));
<Parent>
<Child>Child text</Child>
</Parent>
select
XMLElement('Parent',
XMLElement('Child',
XMLElement('GrandChild', 'Grandchild text')));
<Parent>
<Child>
<GrandChild>Grandchild text</GrandChild>
</Child>
</Parent>
DEPTNO DEPTNAME DEPTLOC
------ ---------- ---------
10 MARKETING BOSTON
20 HR BOSTON
30 SALES NEW YORK
40 ENGINEERING NEW YORK
select * from departments;
<Departments>
<Dept>
<Number>10</Number>
<Name>MARKETING</Name>
<Location>BOSTON</Location>
</Dept>
<Dept>
<Number>20</Number>
<Name>HR</Name>
<Location>BOSTON</Location>
</Dept>
<Dept>
<Number>30</Number>
<Name>SALES</Name>
<Location>NEW YORK</Location>
</Dept>
<Dept>
<Number>40</Number>
<Name>ENGINEERING</Name>
<Location>NEW YORK</Location>
</Dept>
</Departments>
select
XMLElement('Departments', XMLAGG(
XMLElement('Dept', XMLConcat(
XMLElement('Number', d.deptno),
XMLElement('Name', d.deptname),
XMLElement('Location', d.deptloc)))))
from departments d;
In each of the first two XMLElement() calls, the content of the element is created by a nested XML function call. To create a hierarchically structured XML document of parent and child nodes, you nest the XMLElement() calls within an SQL statement.
XMLElement('Departments', XMLAgg (
The XMLAgg() aggregate is used for the second argument, indicating that the content for the top-level <Departments> node is a group of aggregated nodes, which means these nodes will be child nodes of a single parent node.
XMLElement('Dept', XMLConcat(
XMLElement('Number', d.deptno),
XMLElement('Name', d.deptname),
XMLElement('Location', d.deptloc)))))
These three embedded XMLElement() calls create as many <Dept> child nodes as necessary to wrap the rows of data that are returned from the DEPARTMENTS table.
<Departments>
<Dept>
<Number>10</Number>
<Name>MARKETING</Name>
<Location>BOSTON</Location>
</Dept>
</Departments>
<Departments>
<Dept>
<Number>20</Number>
<Name>HR</Name>
<Location>BOSTON</Location>
</Dept>
</Departments>
<Departments>
<Dept>
<Number>30</Number>
<Name>SALES</Name>
<Location>NEW YORK</Location>
</Dept>
</Departments>
<Departments>
<Dept>
<Number>40</Number>
<Name>ENGINEERING</Name>
<Location>NEW YORK</Location>
</Dept>
</Departments>
This is not valid XML syntax because there are four instances of the <Departments> document element. This demonstrates how important it is to use the IsValidXML() function to ensure that the XML that you create with the function library can be parsed as XML. Furthermore, if you are using schemas, you are also responsible for returning well-formed XML (XML that conforms to the structure that is specified by the schema).
<EmployeesByDepartment>
<Dept DeptNo=“10“>
<Name>ACCOUNTING</Name>
<Location>NEW YORK</Location>
<Employees>
<Employee EmpNo=“7782“>
<Name>CLARK</Name>
<Job>MANAGER</Job>
<Manager>7839</Manager>
<Salary>2450</Salary>
</Employee>
<Employee EmpNo=“7839“>
<Name>KING</Name>
<Job>PRESIDENT</Job>
<Salary>5000</Salary>
</Employee>
...
</Employees>
</Dept>
...
<EmployeesByDepartment>
CREATE temp table emp_grouping AS
SELECT deptno, XMLElement ('Employees', XMLAGG (
XMLElement ('Employee', XMLAttributes ('EmpNo', empno),
XMLConcat (
xmlelement ('name', name),
xmlelement ('job', job),
xmlelement ('manager', mgr),
xmlelement ('salary', sal),
xmlelement ('comm', comm)))))
AS xml FROM emp INNER JOIN dept
ON emp.deptno = dept.deptno
GROUP BY deptno;
SELECT XMLElement('EmployeesByDepartment', XMLAGG(
XMLElement('Dept', XMLAttributes('DeptNo', deptno), XMLConcat(
XMLElement('Name', D.DNAME),
XMLElement('Location', D.LOC),
emp_grouping.xml))))
FROM dept INNER JOIN emp_grouping
ON dept.deptno = emp_grouping.deptno;