2011-10-04 60 views
0

我需要截斷一些使用XSLT 1.0通過HTML格式化的文本;不過,我需要確保所有打開的標籤在我的限制結束時都會關閉。使用XSLT安全地截斷通過HTML安全設置的文本

目前,我已經能夠將我的文本修剪爲設置的字符數限制,但超過限制的任何html標記都沒有正確關閉,導致與其他公告不匹配的格式。

例子:

<div><p>This is my example</p></div> 

如果我設置12的字符限制我留下:

<div><p>This 

我真正需要的是它看起來更像是這樣的:

<div><p>This</p></div> 

這就是我對當前正在工作的代碼截斷文本,但它不安全保持html結束標籤:

<xsl:strip-space elements="*"/> 

<!-- limit: the truncation limit --> 
<xsl:variable name="limit" select="600"/> 

<!-- t: Total number of characters in the set --> 
<xsl:variable name="t" select="string-length(normalize-space(//body))"/> 

<xsl:template match="@Body" mode="truncate"> 
     <xsl:variable name="preceding-strings"> 
       <xsl:copy-of select="preceding::text()[ancestor::body]"/> 
     </xsl:variable> 

     <!-- p: number of characters up to the current node --> 
     <xsl:variable name="p" select="string-length(normalize-space($preceding-strings))"/> 

     <xsl:if test="$p &lt; $limit"> 
       <xsl:element name="{name()}"> 
         <xsl:apply-templates select="@*" mode="truncate"/> 
         <xsl:apply-templates mode="truncate"/> 
       </xsl:element> 
     </xsl:if> 
</xsl:template> 

<xsl:template match="text()" mode="truncate"> 
     <xsl:variable name="preceding-strings"> 
       <xsl:copy-of select="preceding::text()[ancestor::body]"/> 
     </xsl:variable> 

     <!-- p: number of characters up to the current node --> 
     <xsl:variable name="p" select="string-length(normalize-space($preceding-strings))"/> 

     <!-- c: number of characters including current node --> 
     <xsl:variable name="c" select="$p + string-length(.)"/> 

     <xsl:choose> 
       <xsl:when test="$limit &lt;= $c"> 
         <xsl:value-of select="substring(., 1, ($limit - $p))"/> 
         <xsl:text>&#8230;</xsl:text> 
       </xsl:when> 
       <xsl:otherwise> 
         <xsl:value-of select="."/> 
       </xsl:otherwise> 
     </xsl:choose> 
</xsl:template> 

<xsl:template match="@*" mode="truncate"> 
     <xsl:attribute name="{name(.)}"><xsl:value-of select="."/></xsl:attribute> 
</xsl:template> 

回答

3

我想你可能會被XSLT默認規則咬住,它剝去標記並返回文本。爲了保持標記,你需要包括如下規則:

<xsl:template match="*"> 
    <xsl:copy> 
     <xsl:apply-templates/> 
    </xsl:copy> 
    </xsl:template> 

我能簡化代碼,並得到它的工作是這樣的:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:strip-space elements="*"/> 

    <!-- limit: the truncation limit --> 
    <xsl:variable name="limit" select="12"/> 

    <xsl:template match="text()"> 
    <xsl:variable name="preceding-strings"> 
     <xsl:copy-of select="preceding::text()[ancestor::body]"/> 
    </xsl:variable> 

    <!-- p: number of characters up to the current node --> 
    <xsl:variable name="p" select="string-length(normalize-space($preceding-strings))"/> 

    <!-- c: number of characters including current node --> 
    <xsl:variable name="c" select="$p + string-length(.)"/> 

    <xsl:choose> 
     <xsl:when test="$limit &lt;= $c"> 
     <xsl:value-of select="substring(., 1, ($limit - $p))"/> 
     <xsl:text>&#8230;</xsl:text> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:value-of select="."/> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 

    <xsl:template match="*"> 
    <xsl:copy> 
     <xsl:apply-templates/> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 
+0

謝謝你的代碼。不幸的是,它仍在修剪結束標籤。 – FenrisFenrir