SQLの実行結果をXML化した後にHTML化して出力する
SQLの実行結果をXMLで出力する方法を身につけたので、それをXSLTを使用してHTML化する。
XSLTのデータベース内への取込み
Oracle Database上でXSLT変換をするためには、使用するXSLTをデータベース内に取り込む必要がある。
Oracle DatabaseではXMLを格納するための専用型XMLTypeがあり、VARCHAR2、NUMBERといった型と同列に扱われている。(それほど本気でOracleはXMLをOracle 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>