代码之家  ›  专栏  ›  技术社区  ›  martin.malek

在XSLT转换中分解BizTalk

  •  2
  • martin.malek  · 技术社区  · 15 年前

    我正在将XML接收到Biztalk中。一部分是元素,值是用逗号分隔的ID

    <Stores>15,34</Stores>
    

    我要把这个变成

    <Stores>
        <Store>Store 1</Store>
        <Store>Store 4</Store>
    </Stores>
    

    我需要做的是将值分解为逗号,获取每个值并从数据库中获取值(15->存储1,34->存储2)。

    如何在XSLT中进行分解,如何从数据库中获取每个分解值的值。我已经在数据库中有了这个过程,只需要知道如何调用它。

    3 回复  |  直到 15 年前
        1
  •  2
  •   Tomalak    15 年前

    下面是一个与XSLT1.0兼容的解决方案,它可以进行分解:

    <!-- straightforward -->
    <xsl:template match="Stores">
      <xsl:copy>
        <xsl:call-template name="explode">
          <xsl:with-param name="str" select="text()" />
        </xsl:call-template>
      </xsl:copy>
    </xsl:template>
    
    <!-- string processing through recursion -->
    <xsl:template name="explode">
      <xsl:param name="str" select="''" />
    
      <xsl:variable name="temp" select="concat($str, ',')" />
      <xsl:variable name="head" select="substring-before($temp, ',')" />
      <xsl:variable name="tail" select="substring-after($temp, ',')" />
    
      <xsl:if test="$head != ''">
        <Store>
          <xsl:value-of select="$head" />
        </Store>
        <xsl:call-template name="explode">
          <xsl:with-param name="str" select="$tail" />
        </xsl:call-template>
      </xsl:if>
    </xsl:template>
    

    输出为 <Stores>15,34</Stores> 将是:

    <Stores>
      <Store>Store 15</Store>
      <Store>Store 34</Store>
    </Stores>
    

    DavidHall的解决方案似乎包含一个指针,用于如何使用XSLT扩展函数从XSLT调用该数据库。

        2
  •  2
  •   David Hall    15 年前

    Biztalk映射器不支持XSLT 2.0(请参阅msdn文档 http://msdn.microsoft.com/en-us/library/aa559261(BTS.10).aspx )因此,如果要使用映射器,则需要使用exslt扩展。

    有一个很棒的职位 here 作者Richard Hallgren,介绍如何在Biztalk映射器中使用exslt。

    另一个想法是关于另一种解决方案。现在还不清楚您是否必须一个接一个地进行数据库调用—是否可以进行单个调用?

    可以为存储过程提供一个带分隔符的字符串作为参数,然后使用一个函数来分解该字符串。我在下面包含了这样一个函数的例子,这个例子是一个表函数。您可以在Web上找到许多其他实现。

    使用table函数,您可以在存储查找过程中针对这个问题进行联接。

    如果这满足了您的需要,它应该会快得多,因为您现在只执行一次数据库命中,并且可以执行设置操作以返回存储列表。

    CREATE function fn_ParseCSVString
    (   
        @INPUTCSV varchar(MAX)
    )
    RETURNS @TBL TABLE 
    ( 
        COL1 INT
    )
    AS
    BEGIN
    DECLARE @NUM_STR NVARCHAR(MAX)
    SET @NUM_STR = @INPUTCSV
    
    SET @NUM_STR = REPLACE(@NUM_STR,' ','')     
    -- this will trim any intermediate spaces
    
    WHILE LEN(@NUM_STR) >= 0
    BEGIN 
    
    DECLARE @@SUBSTR VARCHAR(100) 
    IF CHARINDEX(',',@NUM_STR,0) <> 0   
    BEGIN   
    SET @@SUBSTR = SUBSTRING(@NUM_STR,0,CHARINDEX(',',@NUM_STR,0))   
    INSERT INTO @TBL VALUES(@@SUBSTR)  
    END 
    ELSE   
    BEGIN   
    INSERT INTO @TBL VALUES(@NUM_STR)   
    BREAK   
    END  
    
    SET @@SUBSTR = @@SUBSTR + ',' 
    
    SET @NUM_STR = SUBSTRING(@NUM_STR, CHARINDEX(',',@NUM_STR,0) + 1, LEN(@NUM_STR)) 
    
    END
    RETURN
    END
    
        3
  •  1
  •   Jim Garrison    15 年前

    我假设您知道如何编写整个转换,但需要有关包含存储编号的字符串的标记化技术的帮助。

    如果您使用的是XSLT2.0,请查看tokenize()函数的定义。这将在指定的分隔符处拆分字符串值,从而允许您执行此转换。在XSLT1中,您可以查看exslt regex扩展函数。