【IT168 技术文档】在2006年,IBM推出了新一代的数据库服务器DB2 9.这是唯一基于开放标准的混合数据服务器,能够在单一请求中无缝管理关系型和 pureXML 数据。IBM DB2 9采用一种自然反映 XML 结构的层次结构来存储 XML 数据。这种结构中的 pureXML 技术通过提供对 XML 数据的简单、高效的存取,可以充分发挥 XML 的潜能。通过使用DB2 9作为面向服务架构 (SOA) 的核心,可以实现 XML 与关系型数据的无缝、高效集成。现在IBM 又推出了DB2 V9.5,提供了XSLT支持,允许将XML数据转换为其他格式。在DB2 V9.5中可以使用新的 XSLTRANSFORM 函数将数据库中的 XML 文档转换为 HTML、纯文本或其他格式的 XML。
首先,从一个大家常见例子来看看为什么XML需要XSLT,XSLT对于XML有什么意义。要理解XSLT,则先来看看一个HTML的例子。
Hypertext Markup Language,中文也就是超文本链接标示语言,是网络的通用语言,一种简单、通用的全置标记语言。HTML将数据内容与表现融为一体,可修改性、数据可检索性比较差,当我们使用HTML时,标记只是简单的表示内容和显示形式,而与表示的内容没有任何关联,为文档的进一步处理带来极大的不便,例如我们要表示一个唱片店的相关CD,用HTML的表示如下:
<html> <body> <h2>My CD Collection</h2> <table border="1"> <tr> <td>Empire Burlesque</td><td>Bob Dylan</td> </tr> </table> </body> </html>
从这个表示,我们不能直观的从标记<td>了解到Empire Burlesque代表什么。而XML是一种元标记语言,没有许多固定的标记,为开发人员提供了更大的灵活性,并且XML将内容和其表现分开,使用户之间的数据交换更加方便,可重用性更强。比如唱片店的CD用XML表示如下:
<?xml version="1.0"?> <catalog> <cd> <title>Empire Burlesque</title> <artist>Bob Dylan</artist> <country>USA</country> <company>Columbia</company> <price>10.90</price> <year>1985</year> </cd> </catalog>
从XML的表示,很容易就知道了Empire Burlesque表示的是CD的名字。
但是从这个例子我们也可以看到XML是一种数据文件。也就是说XML提供的是数据原料,但是并没有提供其表现的形式。那怎么样利用原料,来实现我们需要的像HTML这样的有表现形式的产品呢,在这里就需要引入一个新的概念XSL。
什么是XSL呢?
XSL 指扩展样式表语言(EXtensible Stylesheet Language)。万维网联盟开始发展 XSL 的起因是由于对基于 XML 的样式表语言的需求。XSL包括三部分:
XSLT 一种用于转换 XML 文档的语言。
XPath 一种用于在 XML 文档中导航的语言。
XSL-FO 一种用于格式化 XML 文档的语言。
在这篇文章里,我们将重点介绍XSLT的部分.
XSLT的英文标准名称为eXtensible Stylesheet Language Transformation。根据W3C的规范说明书(http://www.w3.org/TR/xslt),最早设计XSLT的用意是帮助XML文档(document)转换为其它文档。但是随着发展,XSLT已不仅仅用于将XML转换为HTML或其它文本格式,更全面的定义应该是:
XSLT是一种用来转换XML文档结构的语言。
从前面唱片店的例子可以看到,XML定义了信息的内容,却没有定义信息该如何表达。这实际上就是XML的长处,它把内容和形式分离了,这样同一个内容可以有不同的表达。打个比方说XML提供了很多的数据原料,相同的数据原料可以用不同的“模板”来展示,那怎么样从数据原料里面去找到所需要的内容,并把这些内容组合成可以展示的不同的“模板”的形状呢?这时我们就需要一个类似“筛子”一样的东西,把需要的东西选出来,并放到“模板”里面去,形成最终需要的产品。这个“筛子”一样的东西就是对XML内容做了一个XSLT的变换。而这个“模板”就是XML内容的表达,一般是通过XSL(XML Style Language)和CSS(Cascading Style Sheets 层叠样式表)来实现。
在DB2 V9.5便增加了XSLT变换的新功能,可以使用新的 XSLTRANSFORM 函数将数据库中的 XML 文档转换为 HTML、纯文本或其他格式的 XML。此功能类似于 XML Extender 提供的 XSLT 变换。您可以转换 XML 文档的部分或全部内容,并可以使用 XPath 查询语言和 XSLT 的内置函数来选择或重新排列数据。
DB2 V9.5中XSLTRANFORM函数的定义如下:
>>-XSLTRANSFORM-------------------------------------------------> .-AS CLOB(2G)-------. >--(--xml-document--USING--xsl-stylesheet--+----------------------+--+-------------------+--)->< '-WITH--xsl-parameters-' '-AS--| data-type |-' data-type .-(-- -1--)-----. |--+-+-CHARACTER-+--+---------------+--------------------------+--| | '-CHAR------' '-(--integer--)-' | +-+-VARCHAR----------------+--(--integer--)-----------------+ | '-+-CHARACTER-+--VARYING-' | | '-CHAR------' | | .-(--1M--)-------------. | +-+-CLOB------------------------+--+----------------------+-+ | '-+-CHARACTER-+--LARGE OBJECT-' '-(--integer--+---+--)-' | | '-CHAR------' +-K-+ | | +-M-+ | | '-G-' | | .-(--1M--)-------------. | '-+-BLOB----------------+--+----------------------+---------' '-BINARY LARGE OBJECT-' '-(--integer--+---+--)-' +-K-+ +-M-+ '-G-'
下面,将同样使用唱片店的例子来帮助大家更好的理解XSLTRANFORM函数的实现。每个XML文档里包含了多个CD的内容,每张CD包含了CD的名字,唱片作者等等内容,一个简单XML的例子如下:
<?xml version="1.0"?> <catalog> <cd> <title>Empire Burlesque</title> <artist>Bob Dylan</artist> <country>USA</country> <company>Columbia</company> <price>10.90</price> <year>1985</year> </cd> </catalog>
对这个XML文档做XSLT 变换的用途在于抽取 XML 记录中的信息并创建可在浏览器中查看的 HTML Web 页面。为此,应使用以下 XSLT 样式表,该样式表存储在数据库中
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html> <body> <h2>My CD Collection</h2> <table border="1"> <tr bgcolor="#9acd32"> <th align="left">Title</th> <th align="left">Artist</th> </tr> <xsl:for-each select="catalog/cd"> <tr> <td><xsl:value-of select="title"/></td> <td><xsl:value-of select="artist"/></td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet>
为了存放XML数据和其对应的XSLT变换表,首先建立一个表XML_TEST,表的定义如下:
CREATE TABLE XML_TEST (DOCID INTEGER, XML_DOC XML, XSL_DOC CLOB(1M));
在这个表里,XML_DOC放XML文件,XSL_DOC放其对应的XSLT样式表。
将XML和对应的XSLT插入表中,
INSERT INTO XML_TEST VALUES
(1, ‘<?xml version="1.0"?> <catalog> <cd> <title>Empire Burlesque</title> <artist>Bob Dylan</artist> <country>USA</country> <company>Columbia</company> <price>10.90</price> <year>1985</year> </cd> </catalog>', '<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html> <body> <h2>My CD Collection</h2> <table border="1"> <tr bgcolor="#9acd32"> <th align="left">Title</th> <th align="left">Artist</th> </tr> <xsl:for-each select="catalog/cd"> <tr> <td><xsl:value-of select="title"/></td> <td><xsl:value-of select="artist"/></td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet>');
调用 XSLTRANSFORM 内置函数来变换 XML 文档。
SELECT XSLTRANSFORM (XML_DOC USING XSL_DOC AS CLOB(1M)) FROM XML_TEST;
变换生成的HTML文档如下:
<html> <body> <h2>My CD Collection</h2> <table border="1"> <tr bgcolor="#9acd32"> <th aligh="left">Title</th><th aligh="left">Artist</th> </tr> <tr> <td>Empire Burlesque</td><td>Bob Dylan</td> </tr> </table> </body> </html>
使用IE浏览器打开生成的HTML文档,可以从IE浏览器看到生成的展示如下图所示
IBM DB2 V9.5所提供的XSLTRANSFORM 功能还不仅仅局限于此。XSLTRANSFORM的一个重要特征是它能够在运行时接受参数。如果缺少此能力,那么您将需要维护一个较大的 XSLT 样式表库,XML 数据查询的每个变体使用一个样式表,或者,您需要手动为每种新查询编辑您的样式表。参数传递允许您使样式表的标准行为独立于特定查询的定制要求或独特要求。在仔细设计核心样式表后,您可以不再考虑它们,并可以在参数文件中设置任何定制行为。比如在唱片行的例子中,我们希望可以改变表的名字,使其表的名字可以随意的改变。这样我们就需要将表的名字设置为一个参数。为了达到这样的目的,修改在XML_TEST中的XSL_DOC为新的XSLT样式表如下:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:param name="headline"/> <xsl:template match="/"> <html> <body> <h2><xsl:value-of select="$headline"/></h2> <table border="1"> <tr bgcolor="#9acd32"> <th align="left">Title</th> <th align="left">Artist</th> </tr> <xsl:for-each select="catalog/cd"> <tr> <td><xsl:value-of select="title"/></td> <td><xsl:value-of select="artist"/></td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet>
在这个新的XSLT文档中,增加了<xsl:param name="headline"/>语句来传入一个参数,并且将以前的表的名字修改为<h2><xsl:value-of select="$headline"/></h2>使用参数。
为了方便传入参数,我们还需要一个数据库的表来存储传入的参数。
CREATE TABLE PARAM_TAB (DOCID INTEGER, PARAM VARCHAR(1000));
在表PARAM_TAB中插入相关的参数数据
INSERT INTO PARAM_TAB VALUES
(1,
'<?xml version="1.0"?>
<params xmlns="http://www.ibm.com/XSLTransformParameters">
<param name="headline">My New CD Collection</param>
</params>'
);
在这里把传入的参数定义为“My New CD Collection”
再执行一次XMLTRANFORM函数,并使用参数
SELECT XSLTRANSFORM (XML_DOC USING XSL_DOC
WITH PARAM AS CLOB(1M)) FROM XML_TEST X, PARAM_TAB P WHERE X.DOCID=P.DOCID;
这样传入参数后,可以得到新生成的HTML如下:
<html> <body> <h2>My New CD Collection</h2> <table border="1"> <tr bgcolor="#9acd32"> <th aligh="left">Title</th><th aligh="left">Artist</th> </tr> <tr> <td>Empire Burlesque</td><td>Bob Dylan</td> </tr> </table> </body> </html>
用IE浏览器打开后,新的页面显示如下:
这样的话,就轻松实现了表的名字的转换。如果还要修改表的名字只需要传入相应的参数就可以了,而无需保存多个不同的XSLT变换表。
最后值得注意的是,在使用IBM DB2 V9.5版本的内置 XSLTRANSFORM 函数转换 XML 文档时,有一些重要注意事项和限制。
注意事项:
源 XML 文档必须是单一根并且格式良好。
因为 XSLT 变换在缺省情况下会产生 UTF-8 字符,所以插入到使用字符数据类型定义的列中时,输出流会丢失字符。
限制:
仅支持 W3C XSLT V1.0 建议。
所有参数和结果类型必须为 SQL 类型,它们不能是文件名。
不支持包含多个样式表文档的变换(使用 xsl:include 声明)。
在IBM DB2 V9.5中新增了XMLTRANSFORM函数,提供对XSLT变换的支持,帮助客户将XML文档(document)转换为其它文档。本文从一个唱片店的例子,从HTML和XML的对比来引出了XSLT的概念和重要性。并继续用唱片店的例子来说明如何使用DB2 V9.5提供的XMLTRANSFORM函数实现XSLT变换,以及如何向XSLTRANSFORM函数提供运行时参数,避免维护一个较大的XSLT样式表库,实现XSLT样式表的灵活性。