SQLの実行結果をXML化した後にHTML化して出力する

SQLの実行結果をXMLで出力する方法を身につけたので、それをXSLTを使用してHTML化する。

検証環境

XSLTのデータベース内への取込み

Oracle Database上でXSLT変換をするためには、使用するXSLTをデータベース内に取り込む必要がある。
Oracle DatabaseではXMLを格納するための専用型XMLTypeがあり、VARCHAR2、NUMBERといった型と同列に扱われている。(それほど本気でOracleXMLOracle Databaseに統合したということなのか)
XSLTを格納する表を XSLT_REPOSITORY とし、以下のとおり定義する。

CREATE TABLE XSLT_REPOSITORY (
    name VARCHAR2(100),
    xslt XMLTYPE,
    CONSTRAINT XSLT_REPOSITORY_PK PRIMARY KEY (name)
)
XMLTYPE xslt STORE AS BASICFILE BINARY XML;

ここにXSLTを取り込む方法として、ディレクトリオブジェクト内のXSLTファイルからの取り込みを使用する。XSLTそのものはやはりファイルとして管理するイメージがある。それをロードする形をとりたい。
まずは /var/oracle/xmlport ディレクトリを作成し、データベース上でもディレクトリオブジェクト XMLPORT を /var/oracle/xmlport パス向けに作成する。

CREATE DIRECTORY XMLPORT AS '/var/oracle/xmlport';

作成した /var/oracle/xmlport ディレクトリに、サンプルのXSLTとして sample.xslt を格納する。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="html" encoding="UTF-8"/>

  <xsl:template match="/">
    <xsl:apply-templates/>
  </xsl:template> 

  <xsl:template match="ROWSET">
    <HTML>
    <BODY>
    <TABLE>
    <xsl:apply-templates/>
    </TABLE>
    </BODY>
    </HTML>
  </xsl:template> 

  <xsl:template match="ROW">
    <TR>
        <TD><xsl:value-of select="ID"/></TD>
        <TD><xsl:value-of select="NAME"/></TD>
        <TD><xsl:value-of select="PRICE"/></TD>
    </TR>
  </xsl:template> 
</xsl:stylesheet>

ファイル格納後はデータベースの表 XSLT_REPOSITORY にロードする。普通のINSERT文でできてしまう。

INSERT INTO XSLT_REPOSITORY VALUES( 'sample', XMLType(bfilename('XMLPORT', 'sample.xslt'), NLS_CHARSET_ID('AL32UTF8')) );
COMMIT;

XML×XSLT変換

XSLTがデータベース内に取り込めれば、あとはXML生成機能と組み合わせるだけだ。CLOB型で生成されるHTMLを出力するには前の投稿で作成した「CLOB_PUT_LINE」を使う。

DECLARE
    xmldoc XMLTYPE;
    xsltsheet XMLTYPE;
    html CLOB;
BEGIN
    --データベースにロードしたXSLTを取り出す。
    SELECT xslt INTO xsltsheet FROM XSLT_REPOSITORY WHERE name = 'sample';
    --SQLクエリをXML化する。CLOBではなくXMLDOCUMENTとして取得するためGETXMLではなくGETXMLTYPEを使用する。
    xmldoc := DBMS_XMLGEN.GETXMLTYPE('SELECT * FROM PRODUCT');

    --変換。
    --SELECT XMLTransform(xmldoc, xsltsheet).GETCLOBVAL() INTO html FROM DUAL; でもできる。
    html := xmldoc.transform(xsltsheet).GETCLOBVAL();

    CLOB_PUT_LINE(html);
    DBMS_LOB.FREETEMPORARY(html);
END;
/

出力例

HTML出力は上記XSLTでは1行になるが、見にくいので改行とインデントを入れてある。改行とインデント以外はそのまま。

<HTML>
<BODY>
  <TABLE>
    <TR><TD>4</TD><TD>COMME des GARCONS</TD><TD>4000000</TD></TR>
    <TR><TD>3</TD><TD>MacBookPro</TD><TD>3000000</TD></TR>
    <TR><TD>2</TD><TD>SUNTORY 天然水</TD><TD>2000000</TD></TR>
    <TR><TD>1</TD><TD>Catalyst 2940</TD><TD>1000000</TD></TR>
</TABLE>
</BODY>
</HTML>