我已经和Symphony合作了几个星期,并且掌握了窍门,真的很喜欢所有的基本功能。
我有一个问题,因为我不太确定如何解决这个问题:我有一个我正在从事的项目的新闻/博客页面。有时文章很短,有时很长。我想做的是显示一定数量的段落,但在找到 x 个字符时停止。我找到了计算字符串长度的方法,但我希望它像这样工作。
<p>paragraph with 20 chars</p>
<p>paragraph with 300 chars</p>
<p>paragraph with 500 chars</p>
等。
现在我想配置一个最大 200 个字符。 第二段将超过数量,但我希望内容同时显示在第一段和第二段。 所以它实际上是 320 个字符(不包括 HTML 和空格)。
我希望我不要含糊其辞,有人知道我应该去哪里。最好的选择是编辑我猜的数据源,但这对我来说似乎不是一个干净的方法尽管它应该略微减少负载。
有人愿意为我指出正确的方向吗?
如果我正确阅读了问题,您希望输出最小段落,以便段落中字符的总字符数大于所需的字符数。
例如,如果您有 20、30 和 40 个字符的段落。停止为 19,您只会吐出第一个,停止为 21,您将输出第 1 段和第 2 段 (21<20+30),如果停止号大于 50,您将输出所有三个。
如果这是正确的,下面的输出将完成您需要的 - 如果您更改此行:
<xsl:if test="30 > string-length($prev)">
其中 30 成为要停止的所需字符串长度。
这个 XSLT 模板...
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="ps">
<h2>
<xsl:value-of select="./@name"/>
</h2>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="p">
<xsl:variable name="prev">
<xsl:for-each select="preceding-sibling::node()">
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:variable>
<xsl:if test="30 > string-length($prev)">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
。当应用于本文档时...
<pss>
<ps name="test1">
<p>paragraph with 20 chars</p>
<p>paragraph with 300 chars</p>
<p>paragraph with 500 chars</p>
</ps>
<ps name="test2">
<p>paragraph with 20 chars much greater characters</p>
<p>paragraph with 300 chars</p>
<p>paragraph with 500 chars</p>
</ps>
<ps name="test2">
<p>few chars</p>
<p>few chars</p>
<p>few chars</p>
</ps>
</pss>
。生成此输出。
<h2>test1</h2>
<div>
<p>paragraph with 20 chars</p>
<p>paragraph with 300 chars</p>
</div>
<h2>test2</h2>
<div>
<p>paragraph with 20 chars much greater characters</p>
</div>
<h2>test2</h2>
<div>
<p>few chars</p>
<p>few chars</p>
<p>few chars</p>
</div>
对于狗屎和傻笑,我只是添加我必须做的事情,以实现我想要实现的目标:
<xsl:for-each select="body/p">
<xsl:variable name="prev">
<xsl:for-each select="preceding-sibling::node()">
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:variable>
<xsl:if test="50 > string-length($prev)">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
它可能会帮助其他人寻找这个,所以我想我可以添加我自己的答案。
@stormtroopr的解决方案将起作用,但它具有 O(n^2) 性能:如果段落数翻倍,样式表所花费的时间将增加 4 倍。更好的解决方案是使用递归。在你掌握它之前,这很棘手,但它并不复杂。基本上,您将第一段作为参数传递最大长度:
<xsl:apply-templates select="p[1]">
<xsl:with-param name="length-so-far" select="0"/>
<xsl:with-param name="max-length" select="200"/>
</xsl:apply-templates>
然后每个段落首先输出自己,然后决定是否继续下一个段落:
<xsl:template match="p">
<xsl:param name="length-so-far"/>
<xsl:param name="max-length"/>
<xsl:if test="$length-so-far < $max-length">
<xsl:copy-of select="."/>
<xsl:apply-templates select="following-sibling::p[1]">
<xsl:with-param name="length-so-far" select="$length-so-far + string-length(.)"/>
<xsl:with-param name="max-length" select="$max-length"/>
</xsl:apply-templates>
</xsl:if>
</xsl:template>