2012-12-20 107 views
14

函數normalize-space用一個空格替換空格的序列並修剪提供的字符串。我怎樣才能修剪字符串而不更換空格?有專有的解決方案,如orcl:left-trim,但我正在尋找一個非專有的解決方案。如何修改XSLT中的空間而不用單個空格替換空格?

實施例:

<xsl:value-of select="trim(/Car/Description)"/> 

應開啓

<car> 
    <description> To get more information look at:  www.example.com </description> 
</car> 

"To get more information look at:  www.example.com" 

回答

16

僅使用xslt的解決方案1。0模板:

<xsl:variable name="whitespace" select="'&#09;&#10;&#13; '" /> 

<!-- Strips trailing whitespace characters from 'string' --> 
<xsl:template name="string-rtrim"> 
    <xsl:param name="string" /> 
    <xsl:param name="trim" select="$whitespace" /> 

    <xsl:variable name="length" select="string-length($string)" /> 

    <xsl:if test="$length &gt; 0"> 
     <xsl:choose> 
      <xsl:when test="contains($trim, substring($string, $length, 1))"> 
       <xsl:call-template name="string-rtrim"> 
        <xsl:with-param name="string" select="substring($string, 1, $length - 1)" /> 
        <xsl:with-param name="trim" select="$trim" /> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="$string" /> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:if> 
</xsl:template> 

<!-- Strips leading whitespace characters from 'string' --> 
<xsl:template name="string-ltrim"> 
    <xsl:param name="string" /> 
    <xsl:param name="trim" select="$whitespace" /> 

    <xsl:if test="string-length($string) &gt; 0"> 
     <xsl:choose> 
      <xsl:when test="contains($trim, substring($string, 1, 1))"> 
       <xsl:call-template name="string-ltrim"> 
        <xsl:with-param name="string" select="substring($string, 2)" /> 
        <xsl:with-param name="trim" select="$trim" /> 
       </xsl:call-template> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="$string" /> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:if> 
</xsl:template> 

<!-- Strips leading and trailing whitespace characters from 'string' --> 
<xsl:template name="string-trim"> 
    <xsl:param name="string" /> 
    <xsl:param name="trim" select="$whitespace" /> 
    <xsl:call-template name="string-rtrim"> 
     <xsl:with-param name="string"> 
      <xsl:call-template name="string-ltrim"> 
       <xsl:with-param name="string" select="$string" /> 
       <xsl:with-param name="trim" select="$trim" /> 
      </xsl:call-template> 
     </xsl:with-param> 
     <xsl:with-param name="trim" select="$trim" /> 
    </xsl:call-template> 
</xsl:template> 

測試代碼:

<ltrim> 
    <xsl:call-template name="string-ltrim"> 
     <xsl:with-param name="string" select="' &#10; test '" /> 
    </xsl:call-template> 
</ltrim> 
<rtrim> 
    <xsl:call-template name="string-rtrim"> 
     <xsl:with-param name="string" select="' &#10; test &#10; '" /> 
    </xsl:call-template> 
</rtrim> 
<trim> 
    <xsl:call-template name="string-trim"> 
     <xsl:with-param name="string" select="' &#10; test &#10; '" /> 
    </xsl:call-template> 
</trim> 

輸出:

<test> 
    <ltrim>test </ltrim> 
    <rtrim> 
    test</rtrim> 
    <trim>test</trim> 
</test> 
+0

我喜歡乾淨的解決方案,不必添加額外的庫 - 謝謝你的這個!由於我不得不先問問項目經理,我們是否可以添加額外的庫,這個解決方案對我來說顯然是可取的。我想沒有辦法簡單地把一個參數放在xsl文件的開頭,使所有的字段都被修剪,是嗎?我找到了'',但是這隻適用於像'concat(...)'這樣的其他轉換,導致像'姓氏,名字'而不是'姓氏,名字'的結果。看起來好像沒有這樣簡單的解決方案... –

+2

@MathiasBader:在任何轉換之前,'xsl:strip-space'在源文檔上運行,並刪除僅包含空格的文本節點。它可能不會解決你的問題。最簡單的解決方案可能會創建一個單獨的轉換,它只修剪所選元素的空白,並將其結果用作第二個轉換的輸入。這可以在單個樣式表中使用特定處理器的擴展函數完成,也可以使用外部工具/ api來調用轉換。 –

+0

通過外部工具使用單獨的(預處理)轉換是我也想到的。我只是認爲這個問題似乎很常見,我認爲必須有一個更簡單的XSLT提供的解決方案,我還沒有找到。 –

2

使用FXSL(開源庫XSLT功能編程,在完全寫入XSL T)一個簡單地寫入

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:import href="trim.xsl"/> 

    <xsl:output method="text"/> 
    <xsl:template match="/*/description"> 
    '<xsl:call-template name="trim"> 
     <xsl:with-param name="pStr" select="."/> 
    </xsl:call-template>' 
    </xsl:template> 
</xsl:stylesheet> 

當這個變換所提供的XML文檔應用:

<car> 
    <description> To get more information look at:  www.example.com </description> 
</car> 

有用,正確的結果產生:

'To get more information look at:  www.example.com' 

trim模板如何工作

它修剪左前導空白,然後反轉結果字符串並修剪其前導空格,然後它最終反轉結果字符串。


二,的XPath 2.0溶液

使用

replace(replace(/*/description, '^\s*(.+?)\s*$', '$1'), '^ .*$', '') 

下面是一個XSLT - 2.0 - 基於驗證:

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

<xsl:template match="/"> 
    "<xsl:sequence 
     select="replace(replace(/*/description, '^\s*(.+?)\s*$', '$1'), '^ .*$', '')"/>" 
</xsl:template> 
</xsl:stylesheet> 

當這個變換所提供的XML文檔施加(以上),評估XPath表達式並將此評估的結果複製到輸出中:

"To get more information look at:  www.example.com" 
+0

謝謝您的回答,這聽起來像一個很好的解決方案。我是否確實沒有「原生」解決方案,不需要額外的庫(當然,這更適合導入額外的庫)? –

+0

@MathiasBader,首先,使用FXSL *是本機解決方案--FXSL是一組XSLT模板。如果您不想使用FXSL,可以編寫一個遞歸的XSLT解決方案 - 只要調用已經存在的(並經過測試的)FXSL解決方案,這樣做並不明智。如果您不想保存幾個小時或一天的額外工作,並確保解決方案中沒有錯誤,那麼請從頭開始編寫一個轉換。 FXSL的目的正是爲了將解決方案寫入非常困難或「幾乎不可能」的問題的努力最小化。 –

+0

@MathiasBader,換句話說,我想要這個答案:1.爲您節省大量的時間和開發/驗證工作。 2.爲了讓你知道有一種工具可以顯着減少大多數任務的XSLT開發時間,並且使用XSLT非常自然和直接地完成任務非常困難(「幾乎不可能」)的任務。 –

-2

如果你沒有在中間的任何空間,你可以簡單地使用:

translate(/Car/Description,' ','') 
+0

不錯的想法,但正如你可能已經猜到的那樣,這不幸太簡單了。 –

2

normalize-space(actualSting) - 這樣做。

與XSLT1
+0

這也將刪除中間重複的空格。我正在尋找一個不這樣做的解決方案。 –

3

一個非常簡短的解決方案:

<xsl:template name="trim"> 
      <xsl:param name="str"/> 

      <xsl:choose> 
       <xsl:when test="string-length($str) &gt; 0 and substring($str, 1, 1) = ' '"> 
        <xsl:call-template name="trim"><xsl:with-param name="str"><xsl:value-of select="substring($str, 2)"/></xsl:with-param></xsl:call-template></xsl:when> 
       <xsl:when test="string-length($str) &gt; 0 and substring($str, string-length($str)) = ' '"> 
        <xsl:call-template name="trim"><xsl:with-param name="str"><xsl:value-of select="substring($str, 1, string-length($str)-1)"/></xsl:with-param></xsl:call-template></xsl:when> 
       <xsl:otherwise><xsl:value-of select="$str"/></xsl:otherwise> 
      </xsl:choose> 
     </xsl:template> 
相關問題