2

我已经使用 symphony 工作了几个星期,并且掌握了它的窍门,真的很喜欢所有的基本功能。

我有一个问题,因为我不太确定如何解决这个问题:我有一个我正在从事的项目的新闻/博客页面。有时文章很短有时很长。我想做的是显示一定数量的段落,但在找到 x 数量的字符时停止。我找到了计算字符串长度的方法,但我希望它像这样工作。

<p>paragraph with 20 chars</p>
<p>paragraph with 300 chars</p>
<p>paragraph with 500 chars</p> 

等等

现在我想配置最多 200 个字符。第二段会超过数量,但我希望内容同时显示第一段和第二段。所以它实际上是 320 个字符(不包括 html 和空格)。

我希望我不会含糊其辞,有人知道我应该去哪里。最好的选择是编辑我猜的数据源,但对我来说这似乎不是一个干净的方法,尽管它应该会稍微减少负载。

有人愿意指出我正确的方向吗?

4

3 回答 3

2

@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 &lt; $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>
于 2013-11-04T08:59:24.097 回答
2

对于狗屎和傻笑,我只是添加我必须做的事情,以实现我想要实现的目标:

<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 &gt; string-length($prev)">
                <xsl:copy-of select="."/>
            </xsl:if>
</xsl:for-each>

它可能会帮助其他人寻找这个,所以我想我可以添加自己的答案。

于 2013-11-04T01:05:22.693 回答
2

如果我正确阅读了问题,您希望输出最少的段落,以便段落中字符的总字符数大于所需的字符数。

例如,如果您有 20、30 和 40 个字符的段落。停止为 19 时,您只会吐出第一个,停止为 21 时,您将输出第 1 段和第 2 段(21<20+30),任何大于 50 的停止编号都将输出所有三个。

如果这是正确的,下面的输出将做你需要的 - 如果你改变这一行:

<xsl:if test="30 &gt; 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 &gt; 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>
于 2013-11-03T23:43:44.583 回答