xml - 使用 XSLT 截断 XML

标签 xml xslt xslt-1.0 symphony-cms

我有一个问题要问 SO 社区的聪明人。

下面是 Symphony CMS 生成的 XML 片段.

   <news>
        <entry>
            <title>Lorem Ipsum</title>
            <body>
                <p><strong>Lorem Ipsum</strong></p>
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed malesuada auctor magna. Vivamus urna justo, pulvinar nec, sagittis malesuada, accumsan in, massa. Quisque mi purus, gravida eget, ultricies a, porta in, sem. Maecenas justo elit, elementum vel, feugiat vulputate, pulvinar nec, velit. Fusce vel ante et diam bibendum euismod. Nunc vel nulla non lorem dignissim placerat. Nulla magna massa, auctor et, tempor nec, auctor sit amet, turpis. Quisque odio lacus, auctor at, posuere id, suscipit eget, dui. Phasellus aliquam. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin varius. Phasellus cursus. Cras mattis adipiscing turpis. Sed.</p>
                <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed malesuada auctor magna.</p>
            </body>
        </entry>
    </news>

我需要做的是取一部分 <body>元素,基于指定长度,以博客样式显示:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed malesuada auctor magna. Vivamus urna justo, pulvinar nec, sagittis malesuada, accumsan in, massa. Quisque mi purus, gravida eget, ultricies a, porta in, sem... more

...其中 more 是指向完整新闻项目的链接。我知道我可以选择特定的段落,我也知道我可以使用 substring 函数来获取指定数量的字符。但是,我需要保留文本的格式,即 <body> 中的 HTML 标记。元素。

我意识到这会引发标签关闭问题,但肯定有办法。希望对 XSLT 更有经验的人可以阐明这个问题。

最佳答案

这是我的版本。我已经通过您的 XML 示例对其进行了测试并且它有效。

要调用它,请使用 <xsl:apply-templates select="path/to/body/*" mode="truncate"/> .

<?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="250"/>

<!-- t: Total number of characters in the set -->
<xsl:variable name="t" select="string-length(normalize-space(//body))"/>

<xsl:template match="*" 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>

</xsl:stylesheet>

关于xml - 使用 XSLT 截断 XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/532147/

相关文章:

html - 即使映射,我也无法访问 servlet

java - 如何设置扫描区域 ZXing Scanner

xslt-1.0 - 调用XSLT模板并将所有输出保存到变量

c# - XSLT 扩展对象方法允许的 .NET 返回类型是什么?

xml - XPath 表达式获取所有前面的兄弟 UNTIL 条件满足

xslt - 无法放置格式化日期的逻辑

xslt - 使用 XSLT 1.0 标记和排序

android - 为标记 LinearLayout 找到错误意外的命名空间前缀 "xmlns"

xml - 在引用文献中突出显示某个作者

xml - xsl 1.0 副本在 xsl-fo 输出中丢失格式