2012-08-08 61 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>