如何在转换期间替换多个不同的文本引用

时间:2015-02-20 18:49:56

标签: xml xslt

我在使用转换(xslt 2.0)替换文本时遇到了困难。我的XML文件很大,所以我将它们描述为:

<?xml version="1.0" encoding="utf-8"?>
<sets>
    <set>
        <query>
            <command>
                SELECT * from [A].[dbo].TableOne where id in (select id from [B].[dbo].TableTwo)
            </command>
        </query>
    </set>
    <set>
        <query>
            <command>
                SELECT * from [A].[dbo].TableOne where id not in (select id from [B].[dbo].TableTwo)
            </command>
        </query>
    </set>
</sets>

我想用 [AAA] 替换a) [A] 和b) [B] 替换 [BBB] 的。 到目前为止,我能够进行一次替换a)或b)但不能同时进行两次替换。肯定有一种我尚未学习的方法!

在我的XSL中,这些是一些工作片段:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner"
    xmlns:cl="http://schemas.microsoft.com/sqlserver/reporting/2010/01/componentdefinition"
    xmlns:my="http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition"
    xmlns:saxon="http://icl.com/saxon" extension-element-prefixes="saxon"
>

<!-- Duplicate all nodes and attributes -->
<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="//command">
    <xsl:copy>
        <xsl:value-of select="replace(./text(),$pOldNameforA, $pNewNameforA)" disable-output-escaping="yes" />  
    </xsl:copy>
</xsl:template>

我想包括替换

        <xsl:value-of select="replace(./text(),$pOldNameforB, $pNewNameforB)" disable-output-escaping="yes" />

我不是在搞清楚。 如何应用不同的匹配不止一次替换文本? 谢谢!

1 个答案:

答案 0 :(得分:1)

只需使用一个replace的结果作为另一个replace的输入。另外,我不确定disable-output-escaping的原因是什么,但将command作为CDATA元素可能是更好的选择。

XML输入

<sets>
    <set>
        <query>
            <command>
                SELECT * from [A].[dbo].TableOne where id in (select id from [B].[dbo].TableTwo)
            </command>
        </query>
    </set>
    <set>
        <query>
            <command>
                SELECT * from [A].[dbo].TableOne where id not in (select id from [B].[dbo].TableTwo)
            </command>
        </query>
    </set>
</sets>

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" cdata-section-elements="command"/>
    <xsl:strip-space elements="*"/>

    <xsl:param name="pOldNameforA" select="'\[A\]'"/>
    <xsl:param name="pNewNameforA" select="'[AAA]'"/>
    <xsl:param name="pOldNameforB" select="'\[B\]'"/>
    <xsl:param name="pNewNameforB" select="'[BBB]'"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="command">
        <xsl:copy>
            <xsl:value-of select="replace(replace(.,$pOldNameforA,$pNewNameforA),
                $pOldNameforB,
                $pNewNameforB)"/>            
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

<强>输出

<sets>
   <set>
      <query>
         <command><![CDATA[
                SELECT * from [AAA].[dbo].TableOne where id in (select id from [BBB].[dbo].TableTwo)
            ]]></command>
      </query>
   </set>
   <set>
      <query>
         <command><![CDATA[
                SELECT * from [AAA].[dbo].TableOne where id not in (select id from [BBB].[dbo].TableTwo)
            ]]></command>
      </query>
   </set>
</sets>

如果你有很多替换,你可能只有2个xsl:param是序列,然后使用递归模板迭代它们。

预先提供更多代码,但未来的更新只会发送到xsl:param(可以在运行时传入)。

示例(使用相同的输入产生与上面相同的结果)

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" cdata-section-elements="command"/>
    <xsl:strip-space elements="*"/>

    <xsl:param name="oldNames" select="('\[A\]','\[B\]')"/>
    <xsl:param name="newNames" select="('[AAA]','[BBB]')"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="command[$oldNames]">
        <xsl:copy>
            <xsl:call-template name="replace">
                <xsl:with-param name="string" select="."/>
                <xsl:with-param name="old" select="$oldNames"/>
                <xsl:with-param name="new" select="$newNames"/>
            </xsl:call-template>
        </xsl:copy>
    </xsl:template>

    <xsl:template name="replace">
        <xsl:param name="string"/>
        <xsl:param name="old"/>
        <xsl:param name="new"/>
        <xsl:variable name="newString">
            <xsl:value-of select="replace($string,$old[1],$new[1])"/>            
        </xsl:variable>
        <xsl:choose>
            <xsl:when test="count($old) > 1">
                <xsl:call-template name="replace">
                    <xsl:with-param name="string" select="$newString"/>
                    <xsl:with-param name="old" select="$old[position() > 1]"/>
                    <xsl:with-param name="new" select="$new[position() > 1]"/>
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$newString"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

如果没有替换,只需将2个参数设为空序列(再次,可以在运行时传入):

<xsl:param name="oldNames" select="()"/>
<xsl:param name="newNames" select="()"/>