此XSLT 2.0轉化:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="no"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pmaxChars" as="xs:integer" select="200"/>
<xsl:variable name="vPass1">
<xsl:apply-templates select="/*"/>
</xsl:variable>
<xsl:template match="node()|@*" mode="#default pass2">
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="#current"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="$vPass1" mode="pass2"/>
</xsl:template>
<xsl:template match=
"text()[sum(preceding::text()/string-length()) ge $pmaxChars]"/>
<xsl:template match="text()[not(following::text())]" mode="pass2">
<xsl:variable name="vPrecedingLength"
select="sum(preceding::text()/string-length())"/>
<xsl:variable name="vRemaininingLength"
select="$pmaxChars -$vPrecedingLength"/>
<xsl:sequence select=
"replace(.,
concat('(^.{0,', $vRemaininingLength, '})\W.*'),
'$1'
)
"/>
</xsl:template>
</xsl:stylesheet>
當所提供的XML文檔應用:
<p>Lorem ipsum dolor sit amet, <b>consectetur adipisicing</b> elit, <i>sed do<sup>2</sup></i> eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
產生想要的,正確的結果(一個XML文檔,其中所有文本節點的總長度不超過200,截斷在字邊界上執行,這是truncatio n,其中最大可能的總剩餘串長度):
<p>Lorem ipsum dolor sit amet, <b>consectetur adipisicing</b> elit, <i>sed do<sup>2</sup></i> eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut</p>
說明:
這是接受的文本字符的最大數目爲全局/外部參數$pmaxChars
一個通用的解決方案。
這是一個雙通解決方案。在pass1中,identity rule被模板覆蓋,該模板刪除所有起始字符都具有索引(在所有文本節點的總體連接中)的大於最大允許字符數的文本節點。因此,pass1的結果是一個XML文檔,其中最大允許長度的「break」出現在最後一個文本節點中。
在第2遍中,我們使用與最後一個文本節點匹配的模板覆蓋身份規則。我們使用replace()
功能:
....
replace(.,
concat('(^.{0,', $vRemaininingLength, '})\W.*'),
'$1'
)
這將導致整個字符串進行匹配,並在括號中的子表達式來代替。這個子表達式是動態構造的,並匹配從字符串開頭開始幷包含從0到$vRemaininingLength
(允許的最大長度減去前面所有文本節點的總長度)字符的最長子字符串,緊接着是字邊界字符。
UPDATE:
爲了擺脫導致元素,由於修整沒有文本節點後代(是「空」),只需添加其它的模板:
<xsl:template match=
"*[(.//text())[1][sum(preceding::text()/string-length()) ge $pmaxChars]]"/>
這不是一個XSLT問題。最好的方法是在JavaScript/jQuey中處理這個問題,在後代節點中累積文本的長度,直到找到一個達到您的限制然後殺死其餘部分。 – 2012-05-15 03:38:33
@torazaburo:實際上,這可以通過XSLT 2.0轉換來實現,解決方案並不困難。 –
Iddo:其實這個單詞,其結尾字符是第200個字符是「ut」。 :) –