在SSIS的XML任务中使用/实现exsl函数node-set()
我正在尝试将 XSL 转换应用于 SSIS 包 XML 任务内的 XML 文件。
一切都很好,但不幸的是,我的 XSL 的“可移植性”比正常情况稍差一些,因为我需要使用函数 node-set()
。 我的 XSL 的一个简化示例是:
<xsl:for-each select="msxsl:node-set($familyNames)/token">
<xsl:call-template name="PersonNameComponent">
<xsl:with-param name="nameComponentType" select="'S'" />
<xsl:with-param name="nameComponentSeqNo" select="number($noOfGivenNames) + position()" />
<xsl:with-param name="nameComponent" select="." />
<xsl:with-param name="nameTypeName" select="$familyName" />
<xsl:with-param name="roleCode" select="$roleCode" />
</xsl:call-template>
</xsl:for-each>
我在样式表声明中使用以下命名空间:
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
这适用于 VS IDE、XMLSpy(只要我将 XSLT 引擎设置为 MSXML)等。但是,当我尝试执行包中的 XML 任务出现以下异常:
错误:XML 任务处出现 0xC002F304,XML 任务:发生错误,并显示以下错误消息:“函数‘msxsl:node-set()’已失败。”。
我使用 VS2005 来设计包,因为它是 SSIS 的 2005 版本。
非常感谢任何有关我如何继续的想法。
我正在调用一个实现 EXSLT str:split 函数的模板,以将字符串“标记”为其组成元素,例如“Kermit T Frog”将返回如下:
<token>Kermit</token>
<token>T</token>
<token>Frog</token>
它存储在变量 $familyNames 中,然后我对其进行迭代通过。 但是,由于这是作为结果树片段返回的,因此我需要使用函数 msxsl:node-set() 来包装它,以便将结果视为节点集。 不知道我还能如何实现上述目标。
这是我从 http://www.exslt.org/ 获得的 str:split 的实现:
<xsl:template name="str:split">
<xsl:param name="string" select="''" />
<xsl:param name="pattern" select="' '" />
<xsl:choose>
<xsl:when test="not($string)" />
<xsl:when test="not($pattern)">
<xsl:call-template name="str:_split-characters">
<xsl:with-param name="string" select="$string" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="str:_split-pattern">
<xsl:with-param name="string" select="$string" />
<xsl:with-param name="pattern" select="$pattern" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="str:_split-characters">
<xsl:param name="string" />
<xsl:if test="$string">
<token><xsl:value-of select="substring($string, 1, 1)" /></token>
<xsl:call-template name="str:_split-characters">
<xsl:with-param name="string" select="substring($string, 2)" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="str:_split-pattern">
<xsl:param name="string" />
<xsl:param name="pattern" />
<xsl:choose>
<xsl:when test="contains($string, $pattern)">
<xsl:if test="not(starts-with($string, $pattern))">
<token><xsl:value-of select="substring-before($string, $pattern)" /></token>
</xsl:if>
<xsl:call-template name="str:_split-pattern">
<xsl:with-param name="string" select="substring-after($string, $pattern)" />
<xsl:with-param name="pattern" select="$pattern" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<token><xsl:value-of select="$string" /></token>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
I'm attempting to apply an XSL transform to an XML file inside an SSIS package XML Task.
All well and good, but unfortunately my XSL is slightly less "portable" than normal as I need to use the function node-set()
. A simplified example of my XSL is:
<xsl:for-each select="msxsl:node-set($familyNames)/token">
<xsl:call-template name="PersonNameComponent">
<xsl:with-param name="nameComponentType" select="'S'" />
<xsl:with-param name="nameComponentSeqNo" select="number($noOfGivenNames) + position()" />
<xsl:with-param name="nameComponent" select="." />
<xsl:with-param name="nameTypeName" select="$familyName" />
<xsl:with-param name="roleCode" select="$roleCode" />
</xsl:call-template>
</xsl:for-each>
I'm using the following namespace in the stylesheet declaration:
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
This works in the VS IDE, XMLSpy (as long as I set the XSLT engine as MSXML), etc. However, when I attempt to execute an XML Task within the package I get the following exception:
Error: 0xC002F304 at XML Task, XML Task: An error occurred with the following error message: "Function 'msxsl:node-set()' has failed.".
I'm using VS2005 to design the package as it's the 2005 version of SSIS.
Any ideas on how I can proceed are greatly appreciated.
I'm calling a template that implements the EXSLT str:split function to"tokenise" a string into it's constituent elements, e.g. "Kermit T Frog" would be returned as follows:
<token>Kermit</token>
<token>T</token>
<token>Frog</token>
This is stored in the variable $familyNames, which I then iterate through. However, as this is returned as a result tree fragment I need to wrap it with the function msxsl:node-set() so that the result is treated as a node set. Not sure how else I can achieve the above.
Here's the implementation of str:split that I obtained from http://www.exslt.org/:
<xsl:template name="str:split">
<xsl:param name="string" select="''" />
<xsl:param name="pattern" select="' '" />
<xsl:choose>
<xsl:when test="not($string)" />
<xsl:when test="not($pattern)">
<xsl:call-template name="str:_split-characters">
<xsl:with-param name="string" select="$string" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="str:_split-pattern">
<xsl:with-param name="string" select="$string" />
<xsl:with-param name="pattern" select="$pattern" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="str:_split-characters">
<xsl:param name="string" />
<xsl:if test="$string">
<token><xsl:value-of select="substring($string, 1, 1)" /></token>
<xsl:call-template name="str:_split-characters">
<xsl:with-param name="string" select="substring($string, 2)" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="str:_split-pattern">
<xsl:param name="string" />
<xsl:param name="pattern" />
<xsl:choose>
<xsl:when test="contains($string, $pattern)">
<xsl:if test="not(starts-with($string, $pattern))">
<token><xsl:value-of select="substring-before($string, $pattern)" /></token>
</xsl:if>
<xsl:call-template name="str:_split-pattern">
<xsl:with-param name="string" select="substring-after($string, $pattern)" />
<xsl:with-param name="pattern" select="$pattern" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<token><xsl:value-of select="$string" /></token>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我提出了一种解决方法,涉及使用自定义脚本任务而不是 XML 任务来转换 XML。 脚本任务中的代码是:
我正在引用 Mvp.Xml 项目(可在 CodePlex 上获得)程序集,该程序集提供 EXSLT 函数的 .NET 实现。 作为额外的副作用,这意味着我可以从 xsl 中删除 str:split 模板实现。 我已将 Microsoft msxml 命名空间声明替换为以下内容:
直接调用 str:split 函数(无需将其存储在变量中)。
我知道的唯一含义是我需要将 Mvp.Xml 安装到将安装 SSIS 的服务器的 GAC 中(有关详细信息,请参阅 此处)。
I've come up with a work-around that involves using a custom Script Task instead of the XML Task to transform the XML. The code in the script task is:
I'm referencing the Mvp.Xml project (available on CodePlex) assembly which provides a .NET implementation of the EXSLT functions. As a bonus side-effect this means I can remove the str:split template implementation from the xsl. I've replaced the Microsoft msxml namespace declaration with the following:
to call the str:split function directly (no need to store it in a variable).
The only implication I'm aware of is that I'll need to install Mvp.Xml into the GAC of the server that SSIS will be installed on (for details see here).