Thomas Kyte the guy of Oracle's Ask Tom page has in his blog a post about creating HTML from cursor. He uses the DBMS_XMLGEN.GETXMLTYPE to create the XML presentation of the cursor and then lXMLData.transform on a generic XSL to convert XML to HTML.

Here is the fncRefCursor2HTML function ( fromTom's blog as is).

CREATE OR REPLACE
FUNCTION fncRefCursor2HTML(rf SYS_REFCURSOR)
RETURN CLOB
as
lHTMLOutput XMLType;
lXSL long;
lXMLData XMLType;
lContext DBMS_XMLGEN.CTXHANDLE;
BEGIN
-- get a handle on the ref cursor --
lContext := DBMS_XMLGEN.NEWCONTEXT(rf);

-- setNullHandling to 1 (or 2) to allow null columns
-- to be displayed
DBMS_XMLGEN.setNullHandling(lContext,1);

-- create XML from ref cursor --
lXMLData := DBMS_XMLGEN.GETXMLTYPE
(lContext,DBMS_XMLGEN.NONE);

-- this is a generic XSL for Oracle's default
-- XML row and rowset tags --
-- " " is a non-breaking space --
lXSL :=
'<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<body>
<table border="1">
<tr bgcolor="cyan">
<xsl:for-each select="/ROWSET/ROW[1]/*">
<th><xsl:value-of select="name()"/></th>
</xsl:for-each>
</tr>
<xsl:for-each select="/ROWSET/*">
<tr>
<xsl:for-each select="./*">
<td><xsl:value-of select="text()"/> </td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>';

-- XSL transformation to convert XML to HTML --
lHTMLOutput := lXMLData.transform(XMLType(lXSL));

-- convert XMLType to Clob --
return lHTMLOutput.getClobVal();
END fncRefCursor2HTML;


Yes I know, the context is not closed. Add DBMS_XMLGEN.closeContext(lContext); in the end.