我有以下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>
而且我只想显示前 200 个字符,但它可能不会在单词中间截断,我想保留格式元素。所以上面的片段在转换后变成:
<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 ...</p>
有谁知道这是否可能?提前感谢!
此 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,截断在字边界上执行,这是截断,剩余的最大可能总字符串长度(:
<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 中,标识规则由删除所有文本节点的模板覆盖,这些文本节点的起始字符具有大于允许的最大字符数的索引(在所有文本节点的总串联中(。因此,pass1 的结果是一个 XML 文档,其中最大允许长度的"中断"发生在最后一个文本节点中。
在第 2 阶段中,我们使用与最后一个文本节点匹配的模板覆盖标识规则。我们使用
replace()
函数:
....
replace(.,
concat('(^.{0,', $vRemaininingLength, '})W.*'),
'$1'
)
这会导致匹配完整的字符串,并替换为括号之间的子表达式。此子表达式是动态构造的,它匹配从字符串开头开始的最长子字符串,其中包含从 0 到 $vRemaininingLength
(允许的最大长度减去前面所有文本节点的总长度(字符,并且紧跟单词边界字符。
更新:
要删除由于修剪而没有文本节点后代("空"(的结果元素,只需添加此附加模板:
<xsl:template match=
"*[(.//text())[1][sum(preceding::text()/string-length()) ge $pmaxChars]]"/>