我正在尝试将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设计软件包,因为它是2005版的SSIS。
非常感谢任何有关我如何进行的想法。
我正在调用一个实现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>
答案 0 :(得分:3)
我提出了一种解决方法,涉及使用自定义脚本任务而不是XML任务来转换XML。脚本任务中的代码是:
Imports System
Imports Microsoft.SqlServer.Dts.Runtime
Imports Mvp.Xml.Common.Xsl
Public Class ScriptMain
' The execution engine calls this method when the task executes.
' To access the object model, use the Dts object. Connections, variables, events,
' and logging features are available as static members of the Dts class.
' Before returning from this method, set the value of Dts.TaskResult to indicate success or failure.
'
' To open Code and Text Editor Help, press F1.
' To open Object Browser, press Ctrl+Alt+J.
Public Sub Main()
Dts.TaskResult = Dts.Results.Failure
If Dts.Variables.Contains("FullSourcePathFileName") AndAlso _
Dts.Variables.Contains("XsltPath") AndAlso _
Dts.Variables.Contains("FullSourceTransformedPathFileName") Then
Dim input As String = CType(Dts.Variables("FullSourcePathFileName").Value, String)
Dim xsl As String = CType(Dts.Variables("XsltPath").Value, String)
Dim output As String = CType(Dts.Variables("FullSourceTransformedPathFileName").Value, String)
Try
Dim xslt As New MvpXslTransform()
xslt.Load(xsl)
xslt.Transform(New XmlInput(input), Nothing, New XmlOutput(output))
Dts.TaskResult = Dts.Results.Success
Catch ex As Exception
Throw
' Look at logging, e.g. Dts.Logging.Log()
End Try
End If
End Sub
End Class
我正在引用Mvp.Xml项目(在CodePlex上可用)程序集,它提供了EXSLT函数的.NET实现。作为奖励副作用,这意味着我可以从xsl中删除str:split模板实现。我已使用以下内容替换了Microsoft msxml名称空间声明:
xmlns:exsl="http://exslt.org/common"
直接调用str:split函数(无需将其存储在变量中)。
我所知道的唯一含义是我需要将Mvp.Xml安装到将安装SSIS的服务器的GAC中(有关详细信息,请参阅here)。