Frage

Ich habe eine Frage für die klug Leute der Gemeinschaft SO.

Im Folgenden ist ein Ausschnitt aus XML erzeugt durch das Symphony CMS .

   <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>

Was ich tun müssen, ist einen Teil des <body> Element zu nehmen, basierend auf einer bestimmten Länge, für die Anzeige im Blog-Stil:

  

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 ... Mehr

... wobei Mehr ist ein Link zum vollständigen News. Ich weiß, dass ich bestimmte Ziffern wählen und ich weiß, kann ich auch den Teil Funktion verwenden, um eine bestimmte Anzahl von Zeichen zu bringen. Ich brauche aber die Formatierung des Textes zu erhalten, das heißt die HTML-Tags innerhalb des <body> Elements.

Ich weiß, das Fragen der Tag Schließung wirft aber es ist sicherlich ein Weg sein. Hoffentlich jemand mehr mit XSLT erfahren kann etwas Licht ins Dunkel bringen.

War es hilfreich?

Lösung

Hier ist meine Version. Ich habe es über die XML-Probe getestet und es funktioniert.

So rufen es, die Verwendung <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>

Andere Tipps

Dies ist die komplette XSLT 1.0-Transformation, die genau das Problem löst.

Diese XSLT-Transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common"
 xmlns:f="http://fxsl.sf.net/"
 xmlns:myAdd="f:myAdd"
 xmlns:myParam="f:myParam"
 exclude-result-prefixes="ext f myAdd myParam"
>
 <xsl:import href="scanl.xsl"/>
 <!--                                         -->
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>
 <!--                                         -->
 <myAdd:myAdd/>
 <myParam:myParam>0</myParam:myParam>
 <!--                                         -->
 <xsl:param name="pTruncateLength" select="772"/>
 <!--                                         -->
   <xsl:variable name="vFun" select="document('')/*/myAdd:*[1]"/>
   <xsl:variable name="vZero" select="document('')/*/myParam:*[1]"/>
 <!--                                         -->
   <xsl:variable name="vrtfScanResults">
           <xsl:call-template name="scanl">
             <xsl:with-param name="pFun" select="$vFun"/>
             <xsl:with-param name="pQ0" select="$vZero" />
             <xsl:with-param name="pList" select="/*/*/body//text()"/>
           </xsl:call-template>
   </xsl:variable>
 <!--                                         -->
   <xsl:variable name="vScanResults"
        select="ext:node-set($vrtfScanResults)"/>
   <xsl:variable name="vindNode" select=
    "count($vScanResults/*[. > $pTruncateLength][1]
                                   /preceding-sibling::*)"/>
 <!--                                         -->
   <xsl:variable name="vrtfTruncInfo">
       <xsl:for-each select="/*/*/body//text()">
 <!--                                         -->
         <xsl:variable name="vPos" select="position()"/>
         <tNode id="{generate-id()}">
           <xsl:attribute name="preserve">
             <xsl:if test="$vPos &lt; $vindNode">
               <xsl:value-of select="string-length(.)"/>
             </xsl:if>
             <xsl:if test="$vPos > $vindNode">
               <xsl:value-of select="0"/>
             </xsl:if>
             <xsl:if test="$vPos = $vindNode">
               <xsl:value-of select=
               "$vScanResults/*[$vindNode+1]
               -
                $pTruncateLength"/>
             </xsl:if>
           </xsl:attribute>
         </tNode>
       </xsl:for-each>
   </xsl:variable>
 <!--                                         -->
   <xsl:variable name="vTruncInfo" select="ext:node-set($vrtfTruncInfo)"/>
 <!--                                         -->
 <xsl:template match="node()|@*">
   <xsl:copy>
     <xsl:apply-templates select="node()|@*"/>
   </xsl:copy>
 </xsl:template>
 <!--                                         -->
 <xsl:template match="text()[ancestor::body]">
   <xsl:variable name="vAllowedLength"
        select="$vTruncInfo/*[@id = generate-id(current())]/@preserve"
   />
 <!--                                         -->
   <xsl:value-of select="substring(.,1,$vAllowedLength)"/>

   <xsl:if test="string-length(.) > $vAllowedLength
               and
                 $vAllowedLength > 0
                ">
     <strong> ...more</strong>
   </xsl:if>
 </xsl:template>
 <!--                                         -->
 <xsl:template match="myAdd:*" mode="f:FXSL">
   <xsl:param name="pArg1"/>
   <xsl:param name="pArg2"/>
   <xsl:value-of select="$pArg1 + string-length($pArg2)"/>
 </xsl:template>
</xsl:stylesheet>

, wenn sie auf der ursprünglichen Quelle XML-Dokument angelegt :

<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>
            <p>This text should not be displayed</p>
        </body>
    </entry>
</news>

erzeugt das gewünschte Ergebnis :

<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 <strong> ...more</strong>
         </p>
         <p/>
      </body>
   </entry>
</news>

Hinweis: die folgende:

  1. Die scanl Sheet aus der FXSL Bibliothek wird importiert. Diese Vorlage wird häufig verwendet, um Daten zu sammeln aus der Verarbeitung eine Liste von Elementen. Die Funktion (die Schablonenanpassung myAdd:*), die die eigentliche Verarbeitung funktioniert als ein Parameter an die scanl Template übergeben. Der andere Parameter, der an mich übergeben werden muss, ist der „erste“ Wert aus der Verarbeitung, die, wenn die übergebene Liste der Elemente zurückgeführt werden soll, ist leer.

  2. Der globale Parameter $pTruncateLength hält die maximale Stringlänge überschreitet, die der Text abgeschnitten werden muss,

Was Sie fragen, ist ein XSLT- Auslassungs Generator.

Auch diese XSLT 1.0-Vorlage geben könnte eine Idee:

Hier ist der wichtigste Kern von ihm:

<xsl:template match="text()" mode="label">
    <xsl:param name="self-x"/>
    <xsl:param name="self-y"/>
    <xsl:variable name="text" select="normalize-space(.)"/>
    <!-- a quick and dirty way to avoid problems with line breaks -->
    <!-- replace the select attribute with this call
         if you want to use a fancier way to escape whitespace
         characters:
          <xsl:call-template name="escape-ws"
            <xsl:with-param name="text" select="." /
          </xsl:call-template
    -->
    <use xlink:href="#text-box" transform="translate({$self-x} 
 {$self-y})"/>
    <!-- text nodes are marked with a little box -->
    <text x="{$self-x + $writing-bump-over}"
          y="{$self-y - $writing-bump-up}"
          style="{$text-font-style}; stroke:none; fill:{$text-color}">
      <xsl:text>"</xsl:text>
      <xsl:value-of select="substring($text,1,$max-text-length)"/>
      <!-- truncate the text node to $max-text-length -->
      <xsl:if test="string-length($text) &gt; $max-text-length">
        <!-- add an ellipsis if necessary -->
        <xsl:text>...</xsl:text>
      </xsl:if>
      <xsl:text>"</xsl:text>
    </text>
  </xsl:template>

Hinweis:

  • müssen Sie die Auslassungspunkte durch einen Link zu ersetzen, aber die Grundidee ist es.
  • dies stellt nur einen kleinen Auszug der alle Skript
  • Sie können nicht alles in es brauchen: Wenn Sie "<use xlink:href="..." benötigen, müssen Sie erklären die XLink-Namensraum

Nach viel Hacking, kam ich zu dieser Lösung:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<!--
    Author: Neil Albrock
    Version: 1.0
    Description: Truncate by a character limit and retain HTML content.
    Usage: 
        <xsl:call-template name="truncate">
            <xsl:with-param name="data" select="path/to/your/body" />
            <xsl:with-param name="length" select="250" />
            <xsl:with-param name="link" select="'href'" />
        </xsl:call-template>
-->

<xsl:template name="truncate">

    <!-- The node set to be worked on. -->
    <xsl:param name="data"/>
    <!-- The desired truncate length. Default to length of data. -->
    <xsl:param name="length" select="string-length($data)"/>
    <!-- More link -->
    <xsl:param name="link"/>

    <xsl:choose>
        <!-- Return whole data if it's within length. -->
        <xsl:when test="string-length($data) &lt;= $length">
            <xsl:copy-of select="$data" />
        </xsl:when>
        <!-- Truncate to desired length. -->
        <xsl:otherwise>
            <xsl:for-each select="$data/*">
                <xsl:variable name="this-node" select="string-length(.)"/>
                <xsl:variable name="preceding-nodes">
                    <xsl:copy-of select="preceding-sibling::*"/>
                </xsl:variable>
                <xsl:variable name="node-sum" select="string-length(normalize-space($preceding-nodes))"/>
                <xsl:variable name="limit" select="$node-sum + $this-node"/>

                <xsl:choose>
                    <xsl:when test="$limit &gt; $length and $node-sum &lt;= $length">
                        <p>
                        <xsl:value-of select="substring(.,1,$length - $node-sum)"/>
                        <xsl:text>&#8230;</xsl:text>
                        <a>
                            <xsl:attribute name="href">
                                <xsl:value-of select="$link"/>
                            </xsl:attribute>
                            <xsl:text>more</xsl:text>
                        </a>
                        </p>
                    </xsl:when>
                    <xsl:when test="$limit &lt; $length">
                        <xsl:copy-of select="."/>
                    </xsl:when>
                    <xsl:otherwise/>
                </xsl:choose>

            </xsl:for-each>
        </xsl:otherwise>
    </xsl:choose>

</xsl:template>

</xsl:stylesheet>

ich die Lösung von Chaotic Pattern verwenden würde es allerdings elegantere; -)

Dies wird eine Episode in Schmerz XSLT verwenden. Ich würde mit einer Skriptsprache wie Perl / Python empfehlen dringend, dies zu versuchen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top