Xalan-C下数据库扩展库—Xalan-C_SQLExtLib实现
来源:互联网 发布:前台点击删除某条数据 编辑:程序博客网 时间:2024/05/16 15:53
XSLT用来描述从一个XML文档到另一个文档的转换规则(逻辑),Xalan-C为XSLT的一个基于C++语言的解析器,根据XSLT所描述的转换规则执行转换。这非常类似脚本语言和脚本解释器,可以理解为XSLT就是一种脚本语言,而Xalan-C则是对应的脚本解释器。
将转换逻辑从代码中分离出来,通过XSLT来是实现,从而可以大大提高程序的可复用性、可扩展性和灵活性。创建全新的或者修改现有的转换业务,只需要编辑转换规则脚本即可,无需修改和构建主程序。
然而,有时,Xalan-C提供的转换规则(功能或者函数)是有限的,需要对其进行扩展。例如,在文档转换时,需要将原文档中的商品类别编号输出为对应的商品类别名称,而商品类别编号和名称的对应关系存在数据库的一张代码表中。因此,需要在XSLT中描述从数据库中获取数据的转换规则,并在Xalan-C中实现这种扩展脚本的功能,这就是本文的主题——Xalan-C下数据库扩展库的实现。
Xalan-C支持函数扩展,创建和使用用户自定义函数,但不支持元素扩展。Xalan-J(Xalan的Java版本)支持元素扩展,且Xalan-J已经实现了一个SQL扩展,见http://xml.apache.org/xalan-j/extensionslib.html#sql。
2. Xalan-C实现自定义函数
2.1. 创建用户自定义函数
用户自定义函数需要继承自Function基类
重载execute()方法,在该方法内实现函数功能,并且通过XObjectFactory工厂返回一个XSLT数据类型
重载clone()方法,允许Xalan创建和保持函数的一个副本
如果需要,隐藏赋值=和等于运算符方法。
// Base header file. Must be first.
#include <xalanc/Include/PlatformDefinitions.hpp>
#include <cmath>
#include <ctime>
#include <xercesc/util/PlatformUtils.hpp>
#include <xalanc/XalanTransformer/XalanTransformer.hpp>
#include <xalanc/XPath/XObjectFactory.hpp>
XALAN_CPP_NAMESPACE_USE
// This class defines a function that will return the square root
// of its argument.
class FunctionSquareRoot : public Function
{
public:
/**
* Execute an XPath function object. The function must return a valid
* XObject.
*
* @param executionContext executing context
* @param context current context node
* @param opPos current op position
* @param args vector of pointers to XObject arguments
* @return pointer to the result XObject
*/
virtual XObjectPtr
execute(
XPathExecutionContext& executionContext,
XalanNode* /* context */,
const XObjectPtr arg,
const Locator* /* locator */) const
{
if (args.size() != 1)
{
executionContext.error("The square-root() function takes one argument!",
context);
}
assert(args[0] != 0);
// Use the XObjectFactory createNumber() method to create an XObject
// corresponding to the XSLT number data type.
return executionContext.getXObjectFactory().createNumber(
sqrt(args[0]->num()));
}
/**
* Implement clone() so Xalan can copy the square-root function into
* its own function table.
*
* @return pointer to the new object
*/
// For compilers that do not support covariant return types,
// clone() must be declared to return the base type.
#if defined(XALAN_NO_COVARIANT_RETURN_TYPE)
virtual Function*
#else
virtual FunctionSquareRoot*
#endif
clone() const
{
return new FunctionSquareRoot(*this);
}
private:
// The assignment and equality operators are not implemented...
FunctionSquareRoot&
operator=(const FunctionSquareRoot&);
bool
operator==(const FunctionSquareRoot&) const;
}
2.2. 安装、卸载用户自定义函数
XalanTransformer类为扩展函数提供安装和卸载方法。
installExternalFunction在XalanTransformer的当前对象上安装扩展函数。
uninstallExternalFunction在XalanTransformer的当前对象上卸载扩展函数。
installExternalFunctionGlobal在全局作用域上安装扩展函数,
uninstallExternalFunctionGlobal在全局作用域上卸载扩展数据。
注意:如果扩展函数作为全局函数安装,那么扩展函数应该是线程安全的。因为多个线程可能同时调用同一个扩展函数。
2.3. 访问用户自定义函数
以下代码片段安装一个名称为“square-root”的本地函数FunctionSquareRoot(求平方根),并且绑定到命名空间http://MyExternalFunction.mycompany.org下。
#include <xalanc/Include/PlatformDefinitions.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xalanc/XalanTransformer/XalanTransformer.hpp>
// You have created a header file for FunctionSquareRoot.
#include <MyFunctions/FunctionSquareRoot.hpp>
// The namespace...
const XalanDOMString
theNamespace("http://MyExternalFunction.mycompany.org");
theXalanTransformer.installExternalFunction(theNamespace,
XalanDOMString("square-root"),
FunctionSquareRoot());
以下是使用扩展函数
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:external="http://ExternalFunction.xalan-c.xml.apache.org" exclude-result-prefixes="external">
<xsl:template match="//area">
<out>
The area of the square is
<xsl:value-of select="@value"/> square units.
The length of each side is
<xsl:value-of select="external:square-root(@value)"/> units
</out>
</xsl:template>
</xsl:stylesheet>
2.4. 其他
2.4.1. 字符串参数中带有单引号
将含有单引号的字符串申明为变量,然后,在函数调用时,使用变量。例如,
使用xpath的concat函数连接字符创“a’c’b”和“123”。
错误的语法如下:
<xsl:value-of select="concat('a'c'b','123')"></xsl:value-of>
正确的语法如下:
<xsl:variable name="var1">a'c'b</xsl:variable>
<xsl:value-of select="concat($var1,'123')"></xsl:value-of>
3. Xalan-C_SQLExtLib
Xalan-C_SQLExtLib库为Xalan-C下的一个数据库扩展函数库,其特性如下:
l 采用ADO连接数据源,具有执行SQL语句及存储过程的能力。
l 支持数据库事务
l 支持多数据源访问,支持同一个任务访问不同数据源的能力。
l 提供数据库连接池特性,按名访问数据库连接。
l 支持带参数的SQL语句。
l 提供缓存和非缓存两种模式。缓存模式下,一条查询语句返回的结果集能够多次使用,从而减少对数据库的访问,提供处理效率。
3.1. 安装、卸载Xalan-C_SQLExtLib
Xalan-C_SQLExtLib.dll导出2个外部函数:
XalanSQLExtLib_Install:安装SQL扩展库
XalanSQLExtLib_UnInstall:卸载SQL扩展库
宿主进程加载Xalan-C_SQLExtLib.dll,调用XalanSQLExtLib_Install安装SQL扩展库后即可使用SQL扩展库提供的扩展函数。当不再需要使用时,调用XalanSQLExtLib_UnInstall卸载SQL扩展库。
注意,部署时,将Xalan-C_SQLExtLib.dll与Xalan-C_1_10D.dll放在同一个目录下。
3.2. 命名空间
http://Xalan-C_SQLExtLib.lijihongye.com
3.3. 扩展函数清单
Xalan-C_SQLExtLib扩展函数包括连接相关函数、查询相关函数、执行SQL语句函数等。
注册函数名
内部函数名
描述
连接相关函数
connect
XalanSQLExFunctionConnect
连接数据库
disconnect
XalanSQLExFunctionDisconnect
关闭连接
查询相关函数
query
XalanSQLExFunctionQuery
查询
open-result-set
XalanSQLExFunctionOpenResultset
执行查询,将结果集缓存
get-from-result-set
XalanSQLExFunctionGetFromResultset
从结果集中获取数据
get-row-count-from-result-set
XalanSQLExFunctionGetRowCountFromResultset
返回结果集中记录函数
get-col-count-from-result-set
XalanSQLExFunctionGetColCountFromResultset
返回结果集中列数
close-result-set
XalanSQLExFunctionCloseResultset
关闭结果集
事务相关函数
begin-transaction
XalanSQLExFunctionBeginTransaction
打开事务
commit-transaction
XalanSQLExFunctionCommitTransaction
提交事务
rollback-transaction
XalanSQLExFunctionRollbackTransaction
回滚事务
执行SQL语句函数
execute
XalanSQLExFunctionExecute
执行非查询SQL语句
3.4. 连接相关函数
3.4.1. connect
connect函数创建一个新连接,并连接到数据源。
参数:
参数1:ConnectName,连接名,字符串类型。
参数2:ConnectString,连接字符串,字符串类型。
返回值:
成功返回
失败返回
3.4.2. disconnect
disconnect函数断开一个连接。
参数:
参数1:ConnectName,连接名,字符串类型。
返回值:
成功返回
失败返回
3.5. 查询相关函数
3.5.1. query
query函数执行一条查询语句,返回查询结构集中第一行指定列的值。
参数:
参数1:QeuryColumnName,需查询的列名,字符串类型。
参数2:ConnectName,连接名,字符串类型。
参数3:SQL,查询SQL语句,字符串类型。
SQL参数能够接受带变量的SQL语句,变量没有名字,没有类型(都视为字符串),只有位置(顺序号),即第几个(字符串)变量。变量用符号“?”表示,选择“?”,是因为该符号在SQL语句中不常出现。若SQL语句中本身含有“?”符号,不需要进行变量替换,则用“??”双波浪号代替。在包含有变量的SQL语句调用中,变量的取值被跟随在参数3后的参数给出,第i个变量取值为第i+3个参数。原则上,有多少个变量,参数3后就应该有多少个参数。
返回值:
如果查询结果集为空,返回“”空字符串;
如果查询结果集函数大于等于1行,则返回首行QeuryColumnName指定的列的值;
如果SQL语句中的参数和实参个数不一致,则返回
如果查询语句非法,则返回
如果查询失败,返回NF,。
其他错误,返回
举例:
不带变量的query调用:在“laton”连接上执行“select maxobjectid from tb_0001”语句,并返回“maxobjectid”字段的值。
<out>
<xsl:value-of select="sqlextlib:query('code','laton',' select maxobjectid from tb_0001"/>
</out>
带变量的query调用:在“laton”连接上执行“select code from tb_0002 where name=’?’”语句,其中where子句中“?”由XSLT参数$name替换并返回“code”列的值。
<out>
<xsl:param name="name" select="'test'"/>
<xsl:value-of select="sqlextlib:query('code','laton','select code from tb_0002 where name='?'',$name)"/>
</out>
3.5.2. open-result-set
query函数一次只能从查询结果集中返回第一行中一个字段的值,若需要获取同一条SQL语句中多个字段的值,则需要对同一SQL语句执行多次,效率低下。open-result-set函数执行一条查询语句,并能缓存结果集,能用于get-from-result-set函数从结果集中多次获取数据,直到close-result-set函数关闭结果集。
参数:
参数1:ResultsetName,结果集名,注意在同一个XSLT文件中不能定义2个相同的结果集。
参数2:ConnectName,连接名,字符串类型。
参数3:SQL,查询SQL语句,同query函数的参数3。
返回值:
如果函数执行成功,返回
如果SQL语句中的参数和实参个数不一致,则返回
如果查询语句非法,则返回
如果查询失败,返回NF,。
其他错误,返回
open-result-set的实现需要考虑结果集的多实例问题。多实例问题可能出现在以下两种场景中。第一种情况是同一个Xalan-C实例同时解析多个不同的XSLT文件,而这些文件中使用open-result-set函数打开了相同结果集,即ResultsetName参数相同;另一种情况则是同一个Xalan-C实例同时执行同一个包含有open-result-set函数的XSLT文件的多个转换任务,例如同时将a.xml和b.xml通过同一个XSLT文件t.xsl转换为a.out和b.out。
如果不考虑结果集多实例问题,则有可能导致SQL扩展库混淆不同实例的结果集,张冠李戴,a.xml的结果集可能会被用于b.xml文件。
解决这一问题的一个思路是结果集增加实例标示符属性。实例标示符可以采用线程ID来进行唯一标示。该方案的一起缺陷即要求一个转换任务需要在同一个线程中完成。
举例:在“laton”连接上执行“select code,name from tb_0002”语句,并将查询结果集缓存为“CodeTable”。
<out>
<xsl:param name="RS_CodeTable" select="sqlextlib:open-result-set('RS_CodeTable','laton',' select code,name from tb_0002')"/>
</out>
3.5.3. get-from-result-set
get-from-result-set从open-result-set打开的结果集中获取数据。
参数:
参数1:ResultsetName,结果集名。
参数2:Row,行号
参数3:Col,列号
返回值:
成功,返回
如果ResultsetName指定的结果集不存在,返回
如果Row行号越界,则返回
如果Col列号越界,则返回
举例:
<out>
<xsl:param name="RS_CodeTable" select="sqlextlib:open-result-set('RS_CodeTable','laton',' select code,name from tb_0002')"/>
<xsl:value-of select="sqlextlib:get-from-result-set('RS_CodeTable',0,1)"/>
</out>
3.5.4. get-row-count-from-result-set
get-row-count-from-result-set返回结果集中记录的函数。
参数:
参数1:ResultsetName,结果集名。
返回值:
成功,返回
如果ResultsetName指定的结果集不存在,返回
3.5.5. get-col-count-from-result-set
get-col-count-from-result-set返回结果集中列的个数。
参数:
参数1:ResultsetName,结果集名。
返回值:
成功,返回
如果ResultsetName指定的结果集不存在,返回
3.5.6. close-result-set
close-result-set关闭open-result-set打开的结果集。
参数:
参数1:ResultsetName,结果集名。
返回值:
成功,返回
如果ResultsetName指定的结果集不存在,返回
举例:
<out>
<xsl:param name="RS_CodeTable" select="sqlextlib:open-result-set('RS_CodeTable','laton',' select code,name from tb_0002')"/>
<xsl:value-of select="sqlextlib:get-from-result-set('RS_CodeTable',0,1)"/>
<xsl:param name=" RS_CodeTable" select="sqlextlib:close-result-set('RS_CodeTable')"/>
</out>
3.6. 执行SQL语句函数
3.6.1. execute
execute函数执行一条SQL语句。
参数:
参数1:ConnectName,连接名,字符串类型。
参数2:SQL,SQL语句,参见query函数的参数3。
返回值:
成功返回;
若SQL语句中的参数和实参个数不一致,则返回
若SQL语句非法,则返回
其他错误,返回
4. 应用举例
略。
参考文献:
http://xml.apache.org/xalan-c/extensions.html
http://xml.apache.org/xalan-c/extensionslib.html
http://xml.apache.org/xalan-j/extensionslib.html#sql
- Xalan-C下数据库扩展库—Xalan-C_SQLExtLib实现
- xalan
- VS2005编译Xalan-C
- CentOS下编译Xalan-C++1.10.0
- 通过xalan实现关系型数据库到XML的数据交换
- 通过xalan实现关系型数据库到XML的数据交换
- 检查Xalan版本
- Xalan 基本命令行工具
- xalan初步学习
- xalan.jar的下载地址
- 用Xalan-Java分割字符串
- org.apache.xalan.processor.TransformerFactoryImpl
- VS2005(VC8)编译Xalan-C_1_10_0
- 学习笔记——XSLT转换器的使用(Xalan和Saxon)
- xalan.jar版本引发的问题
- org.apache.xalan.processor.TransformerFactoryImpl not found
- apache.xalan.processor.transformerfactoryImpl not found
- XML+XSLT+xalan-j+svg生成地图
- javascript页面跳转
- 架构设计之性能设计经验
- 设置vc开发环境背景颜色
- cugb 1050 拦截导弹 (最长不升子序列)
- Web配置文件(web.config)简介
- Xalan-C下数据库扩展库—Xalan-C_SQLExtLib实现
- 背熟以下文章,就能脱离鼠标,光用键盘操作
- 也谈系统设计的一些原则
- 让vim支持c++代码自动补全功能。
- sizeof的概念,使用方法及主要用途
- Meego Linux 联想Z370(蓝)官方报4999
- http详解
- Balsamiq Mockups Keygen
- JSP页面 点号 温度单位 乱码