如何在转换过程中替换多个不同的文本出现
How to replace multiple different text occurrences during a transformation
我在使用转换 (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>
我想将 a) [A] 替换为 [AAA] 和 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" />
我还没弄清楚。
如何应用不同的匹配多次替换文本?
谢谢!
只需使用一个 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="()"/>
我在使用转换 (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>
我想将 a) [A] 替换为 [AAA] 和 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" />
我还没弄清楚。 如何应用不同的匹配多次替换文本? 谢谢!
只需使用一个 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="()"/>