1 つのアプローチは、XSL スタイルシートです。
しかし、私はあなたのXMLデータ型に追加します. 例えば
<filter>
<and>
<or>
<equals field="MARKET_NAME" value="Chicago" datatype="string"/>
<equals field="MARKET_NAME" value="BOSTON" datatype="string"/>
</or>
<or>
<equals field="RANK" value="1" datatype="number"/>
<equals field="RANK" value="2" datatype="number"/>
</or>
<between field="current_data" arg1="start_date" arg2="End_date" datatype="field"/>
<between field="foo" arg1="20121230" arg2="20130101 01:12:23" datatype="date"/>
<gt field="CUME" value="20" datatype="number"/>
<like field="DMA_NAME" value="%ABC%" datatype="string"/>
</and>
</filter>
次に、XSL (これは単なるサンプルです。これは基本的なスターターにすぎないため、これを改善する必要があります!)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
exclude-result-prefixes="xd"
version="1.0">
<xsl:output method="text"/>
<xsl:template name="string-replace-all">
<xsl:param name="text"/>
<xsl:param name="replace"/>
<xsl:param name="by"/>
<xsl:choose>
<xsl:when test="contains($text,$replace)">
<xsl:value-of select="substring-before($text,$replace)"/>
<xsl:value-of select="$by"/>
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="substring-after($text,$replace)"/>
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="by" select="$by"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="processDatatype">
<xsl:param name="value" />
<xsl:param name="datatype" />
<xsl:choose>
<xsl:when test="$datatype = 'string'">
<xsl:text>'</xsl:text>
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="$value"/>
<xsl:with-param name="replace" select='"'"'/>
<xsl:with-param name="by" select='"''"'/>
</xsl:call-template>
<xsl:text>'</xsl:text>
</xsl:when>
<xsl:when test="$datatype = 'date'">
<xsl:text>to_date('</xsl:text>
<xsl:value-of select="$value"/>
<xsl:text>','yyyymmdd hh24:mi:ss')</xsl:text>
</xsl:when>
<xsl:otherwise><xsl:value-of select="$value"/></xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="gt">
<xsl:value-of select="@field"/>
<xsl:text> > </xsl:text>
<xsl:call-template name="processDatatype">
<xsl:with-param name="value"><xsl:value-of select="@value"/></xsl:with-param>
<xsl:with-param name="datatype"><xsl:value-of select="@datatype"/></xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="lt">
<xsl:value-of select="@field"/>
<xsl:text> < </xsl:text>
<xsl:call-template name="processDatatype">
<xsl:with-param name="value"><xsl:value-of select="@value"/></xsl:with-param>
<xsl:with-param name="datatype"><xsl:value-of select="@datatype"/></xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="between">
<xsl:value-of select="@field"/>
<xsl:text> between </xsl:text>
<xsl:call-template name="processDatatype">
<xsl:with-param name="value"><xsl:value-of select="@arg1"/></xsl:with-param>
<xsl:with-param name="datatype"><xsl:value-of select="@datatype"/></xsl:with-param>
</xsl:call-template>
<xsl:text> and </xsl:text>
<xsl:call-template name="processDatatype">
<xsl:with-param name="value"><xsl:value-of select="@arg2"/></xsl:with-param>
<xsl:with-param name="datatype"><xsl:value-of select="@datatype"/></xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="like">
<xsl:value-of select="@field"/>
<xsl:text> like </xsl:text>
<xsl:call-template name="processDatatype">
<xsl:with-param name="value"><xsl:value-of select="@value"/></xsl:with-param>
<xsl:with-param name="datatype"><xsl:value-of select="@datatype"/></xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="equals">
<xsl:value-of select="@field"/>
<xsl:text> = </xsl:text>
<xsl:call-template name="processDatatype">
<xsl:with-param name="value"><xsl:value-of select="@value"/></xsl:with-param>
<xsl:with-param name="datatype"><xsl:value-of select="@datatype"/></xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="and">
<xsl:for-each select="*">
<xsl:if test="position() != 1">
<xsl:text>and </xsl:text>
</xsl:if>
<xsl:choose>
<xsl:when test="name() = 'like'">
<xsl:text>(</xsl:text>
<xsl:call-template name="like" />
<xsl:text>) </xsl:text>
</xsl:when>
<xsl:when test="name() = 'gt'">
<xsl:text>(</xsl:text>
<xsl:call-template name="gt" />
<xsl:text>) </xsl:text>
</xsl:when>
<xsl:when test="name() = 'lt'">
<xsl:text>(</xsl:text>
<xsl:call-template name="lt" />
<xsl:text>) </xsl:text>
</xsl:when>
<xsl:when test="name() = 'equals'">
<xsl:text>(</xsl:text>
<xsl:call-template name="equals" />
<xsl:text>) </xsl:text>
</xsl:when>
<xsl:when test="name() = 'between'">
<xsl:text>(</xsl:text>
<xsl:call-template name="between" />
<xsl:text>) </xsl:text>
</xsl:when>
<xsl:when test="name() = 'or'">
<xsl:text>(</xsl:text>
<xsl:call-template name="or" />
<xsl:text>) </xsl:text>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template name="or">
<xsl:for-each select="*">
<xsl:if test="position() != 1">
<xsl:text>or </xsl:text>
</xsl:if>
<xsl:choose>
<xsl:when test="name() = 'like'">
<xsl:text>(</xsl:text>
<xsl:call-template name="like" />
<xsl:text>) </xsl:text>
</xsl:when>
<xsl:when test="name() = 'gt'">
<xsl:text>(</xsl:text>
<xsl:call-template name="gt" />
<xsl:text>) </xsl:text>
</xsl:when>
<xsl:when test="name() = 'lt'">
<xsl:text>(</xsl:text>
<xsl:call-template name="lt" />
<xsl:text>) </xsl:text>
</xsl:when>
<xsl:when test="name() = 'equals'">
<xsl:text>(</xsl:text>
<xsl:call-template name="equals" />
<xsl:text>) </xsl:text>
</xsl:when>
<xsl:when test="name() = 'between'">
<xsl:text>(</xsl:text>
<xsl:call-template name="between" />
<xsl:text>) </xsl:text>
</xsl:when>
<xsl:when test="name() = 'and'">
<xsl:text>(</xsl:text>
<xsl:call-template name="and" />
<xsl:text>) </xsl:text>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:template>
<xsl:template match="/filter">
<xsl:text>where </xsl:text>
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="name() = 'and'">
<xsl:call-template name="and" />
</xsl:when>
<xsl:when test="name() = 'or'">
<xsl:call-template name="or" />
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
例:
XMLTYPE として格納されている XSL:
SQL> select * from xsl;
NAME
--------------------
XSL
--------------------------------------------------------------------------------
xml_to_sql
<?xml version="1.0" encoding="WINDOWS-1252"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xd="http:
//www.oxygenxml.com/ns/doc/xsl" exclude-result-prefixes="xd" version="1.0">
<xsl:output method="text"/>
<xsl:template name="string-replace-all">
<xsl:param name="text"/>
...
transform
ここで、入力 XML に対して XMLTYPE 関数を使用して結果を取得します。
SQL> select dbms_xmlgen.convert(xmltype('<?xml-stylesheet type="text/xsl" href="test.xsl"?>
2 <filter>
3 <and>
4 <or>
5 <equals field="MARKET_NAME" value="Chicago" datatype="string"/>
6 <equals field="MARKET_NAME" value="BOSTON" datatype="string"/>
7 </or>
8 <or>
9 <equals field="RANK" value="1" datatype="number"/>
10 <equals field="RANK" value="2" datatype="number"/>
11 </or>
12 <between field="current_data" arg1="start_date" arg2="End_date" datatype="field"/>
13 <between field="foo" arg1="20121230" arg2="20130101 01:12:23" datatype="date"/>
14 <gt field="CUME" value="20" datatype="number"/>
15 <like field="DMA_NAME" value="%AB'C%" datatype="string"/>
16 </and>
17 </filter>').transform(xsl.xsl).getclobval(), 1)
18 from xsl
19 /
DBMS_XMLGEN.CONVERT(XMLTYPE('<
--------------------------------------------------------------------------------
where ((MARKET_NAME = 'Chicago')
or (MARKET_NAME = 'BOSTON')
)
and ((RANK = 1)
or (RANK = 2)
)
and (current_data between start_date and End_date)
and (foo between to_date('20121230','yyyymmdd hh24:mi:ss') and to_date('20130101
01:12:23','yyyymmdd hh24:mi:ss'))
and (CUME > 20)
and (DMA_NAME like '%AB''C%')