2012-08-08 68 views
1

输入:与元件替换XSLT版权符号和其它符号

<text> 
    Please see the registered mark® . 
    Please see the copy right ©. 
    Please see the Trade mark™. 
</text> 

输出:

<text> 
     Please see the registered mark<registeredTrademark></registeredTrademark>. 
     Please see the copy right <copyright></copyright>. 
     Please see the Trade mark <trademark></trademark>. 
    </text> 

我需要更换与元素的所有特殊符号如上所示

可以在任何一个帮助。

感谢

+0

是否有任何理由,你不能用一个简单的文本做更换XML来源? – Flynn1179 2012-08-08 10:20:28

回答

1

该转化是通过避免炭通过炭递归和使用更有效的“最大可能步长”递归

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:my="my:my"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<my:reps> 
    <r char="®">registeredTrademark</r> 
    <r char="©">copyright</r> 
    <r char="™">trademark</r> 
</my:reps> 

<xsl:variable name="vReps" select="document('')/*/my:reps/*"/> 

<xsl:template match="text()" name="multReplace"> 
    <xsl:param name="pText" select="."/> 
    <xsl:param name="pReps" select="$vReps"/> 

    <xsl:if test="$pText"> 
    <xsl:variable name="vTarget" select="$pReps[1]/@char"/> 
     <xsl:choose> 
     <xsl:when test="not($vTarget)"> 
      <xsl:value-of select="$pText"/> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:variable name="vReplacement" select="$pReps[1]"/> 

      <xsl:call-template name="multReplace"> 
      <xsl:with-param name="pText" select= 
      "substring-before(concat($pText, $vTarget), $vTarget)"/> 
      <xsl:with-param name="pReps" select="$pReps[position() >1]"/> 
      </xsl:call-template> 

      <xsl:if test="contains($pText, $vTarget)"> 
      <xsl:element name="{$vReplacement}"/> 
      <xsl:call-template name="multReplace"> 
       <xsl:with-param name="pText" select="substring-after($pText, $vTarget)"/> 
       <xsl:with-param name="pReps" select="$pReps"/> 
      </xsl:call-template> 
      </xsl:if> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:if> 
</xsl:template> 
</xsl:stylesheet> 

当应用于提供的XML文档

<text> 
     Please see the registered mark® . 
     Please see the copy right ©. 
     Please see the Trade mark™. 
</text> 

正确,替换文本,产生

Please see the registered mark<registeredTrademark/> . 
    Please see the copy right <copyright/>. 
    Please see the Trade mark<trademark/>. 
+0

当我的XML有这些特殊字符时,我得到的错误为“给定编码中的无效字符”。有没有什么办法可以避免它 – Patan 2012-08-09 10:51:32

+0

@ User222,你不是在说什么工具发布错误 - XML解析器,XSLT处理器或其他东西。所以很难建议如何避免这种不明的错误。我的猜测是某处(在你没有向我们显示的代码中),你指定/使用了默认编码,它没有这些字符。解决方案是指定utf-8作为编码(如果utf-8是默认值,则不指定任何内容)。 – 2012-08-09 12:00:59

+0

谢谢你的回应。我的Visual Studio不支持此操作:( – Patan 2012-08-10 05:38:21

2

由于这是XSLT 1.0,你将不得不使用递归命名模板依次检查每个字符。

首先,它可能是更灵活地产生一种“查找”在你的XSLT,你可以指定符号列表和所需的元素名称与

<lookup:codes> 
    <code symbol="®">registeredTrademark</code> 
    <code symbol="©">copyright</code> 
    <code symbol="™">trademark</code> 
</lookup:codes> 

,以取代他们( 'lookup'命名空间实际上可以命名为任何东西,只要它在XSLT中是分层的即可)。

然后,访问此,您可以定义一个变量来访问该查询

<xsl:variable name="lookup" select="document('')/*/lookup:codes"/> 

而且,为了查找基于符号实际的代码会做这样的事情(其中$文本)是一个包含正在检查的文本的变量。

<xsl:variable name="char" select="substring($text, 1, 1)"/> 
    <xsl:variable name="code" select="$lookup/code[@symbol = $char]"/> 

所有命名模板要做的,就是检查文本的第一个字符,如果在查找存在与元素替换它,然后递归调用与文本的其余部分的模板。

以下是完整的XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:lookup="lookup" exclude-result-prefixes="lookup"> 
    <xsl:output method="xml" indent="no"/> 

    <lookup:codes> 
     <code symbol="®">registeredTrademark</code> 
     <code symbol="©">copyright</code> 
     <code symbol="™">trademark</code> 
    </lookup:codes> 

    <xsl:variable name="lookup" select="document('')/*/lookup:codes"/> 

    <xsl:template match="text[text()]"> 
     <text> 
     <xsl:call-template name="text"/> 
     </text> 
    </xsl:template> 

    <xsl:template name="text"> 
     <xsl:param name="text" select="text()"/> 
     <xsl:variable name="char" select="substring($text, 1, 1)"/> 
     <xsl:variable name="code" select="$lookup/code[@symbol = $char]"/> 
     <xsl:choose> 
     <xsl:when test="$code"><xsl:element name="{$code}" /></xsl:when> 
     <xsl:otherwise> 
      <xsl:value-of select="$char"/> 
     </xsl:otherwise> 
     </xsl:choose> 
     <xsl:if test="string-length($text) &gt; 1"> 
     <xsl:call-template name="text"> 
      <xsl:with-param name="text" select="substring($text, 2, string-length($text) - 1)"/> 
     </xsl:call-template> 
     </xsl:if> 
    </xsl:template> 

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

当施加到示例XML,下面是输出

<text> 
    Please see the registered mark<registeredTrademark /> . 
    Please see the copy right <copyright />. 
    Please see the Trade mark<trademark />. 
</text>