2009-06-10 12 views
0

Je tente d'appliquer une transformation XSL à un fichier XML dans une tâche XML de package SSIS.Utilisation/implémentation de la fonction exsl node-set() dans la tâche XML de SSIS Tâche

Tout va bien, mais malheureusement mon XSL est légèrement moins "portable" que la normale car j'ai besoin d'utiliser la fonction node-set(). Un exemple simplifié de mon XSL est:

<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> 

J'utilise l'espace de noms suivant dans la déclaration stylesheet:

xmlns:msxsl="urn:schemas-microsoft-com:xslt" 

Cela fonctionne dans l'IDE VS, XMLSpy (aussi longtemps que je mets le XSLT moteur comme MSXML), etc. Cependant, lorsque je tente d'exécuter une tâche XML dans le paquet que je reçois l'exception suivante:

Error: 0xC002F304 at XML Task, XML Task: An error occurred with the following error message: "Function 'msxsl:node-set()' has failed.".

J'utilise VS2005 pour concevoir le paquet comme il est la version 2005 de SSIS.

Toutes les idées sur la façon dont je peux procéder sont grandement appréciées.

J'appelle un modèle qui implémente la fonction EXSLT str: split pour "tokeniser" une chaîne dans ses éléments constituants, par ex. "Kermit T Frog" serait retourné comme suit:

<token>Kermit</token> 
<token>T</token> 
<token>Frog</token> 

Il est stocké dans la variable $, familyNames de itérer que je puis à travers. Cependant, comme ceci est renvoyé comme un fragment d'arbre de résultat je dois l'envelopper avec la fonction msxsl: node-set() pour que le résultat soit traité comme un ensemble de nœuds. Je ne sais pas comment je pourrais réaliser ce qui précède.

est ici la mise en œuvre str: split que j'ai obtenu de 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> 
+0

D'où proviennent les $ familyNames? Pouvez-vous poster la partie de votre XSLT qui le crée? Peut-être existe-t-il un moyen d'éviter complètement node-set(). – Tomalak

+0

Question modifiée pour préciser davantage le problème tel que demandé. – pFrenchie

Répondre

3

Je suis venu avec un travail autour qui consiste à utiliser un script personnalisé des tâches au lieu de la tâche XML pour transformer le XML . Le code de la tâche de script:

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 

Je fais référence au projet Mvp.Xml (disponible sur CodePlex) ensemble qui fournit une implémentation .NET des fonctions EXSLT. Comme un effet secondaire de bonus cela signifie que je peux supprimer l'implémentation str: split template du xsl. Je l'ai remplacé la déclaration d'espace de noms Microsoft MSXML ce qui suit:

xmlns:exsl="http://exslt.org/common" 

pour appeler la str: fonction split directement (pas besoin de stocker dans une variable). La seule implication dont je suis conscient est que j'aurai besoin d'installer Mvp.Xml dans le GAC du serveur sur lequel SSIS sera installé (pour plus de détails, voir here).

Questions connexes