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