使用XSLT安全地截断通过HTML格式化的文本

使用XSLT安全地截断通过HTML格式化的文本,xslt,Xslt,我需要截断一些使用XSLT1.0通过HTML格式化的文本;但是,我需要确保所有打开的标签在我的限制结束时关闭 目前,我已经能够将文本修剪到设置的字符限制,但是任何超过限制的html标记都无法正确关闭,导致格式与其他公告不匹配 例如: <div><p>This is my example</p></div> 这是我的例子 如果我将字符限制设置为12,则剩下: <div><p>This 这个 我真正需要的是它看起来更像这

我需要截断一些使用XSLT1.0通过HTML格式化的文本;但是,我需要确保所有打开的标签在我的限制结束时关闭

目前,我已经能够将文本修剪到设置的字符限制,但是任何超过限制的html标记都无法正确关闭,导致格式与其他公告不匹配

例如:

<div><p>This is my example</p></div>
这是我的例子

如果我将字符限制设置为12,则剩下:

<div><p>This
这个
我真正需要的是它看起来更像这样:

<div><p>This</p></div>
<?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>
这个

这是我为代码所做的,该代码当前用于截断文本,但不能安全地保留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>

我认为您可能被XSLT默认规则咬到了,该规则去掉了标记,只返回文本。要维护标记,您需要包括以下规则:

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

我能够简化您的代码并使其按如下方式工作:

<div><p>This</p></div>
<?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>

我认为您可能被XSLT默认规则咬到了,该规则去掉了标记,只返回文本。要维护标记,您需要包括以下规则:

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

我能够简化您的代码并使其按如下方式工作:

<div><p>This</p></div>
<?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>

谢谢您的代码。不幸的是,它仍然在修剪结束标记。谢谢你的代码。不幸的是,它仍在修剪结束标记。