Получить вводный текст из N символов с XSLT 1.0 из XHTML - PullRequest
0 голосов
/ 30 октября 2010

Как я могу получить первые n символов с XSLT 1.0 из XHTML? Я пытаюсь создать вводный текст для новостей.

  • Все это UTF-8
  • Признак HTML-сущности (  &), одна сущность = один символ
  • HTML-тег осведомлен (добавляет отсутствующие конечные теги)
  • Вводимый HTML всегда действителен
  • Если входной текст превышает n символов, добавьте '...' в конец вывода
  • Входные теги ограничены: a, img, p, div, span, b, strong

Пример ввода HTML:

<img src="image.jpg" alt="">text <a href="http://domain.tld">link here</a>

Пример вывода с 9 символами:

<img src="image.jpg" alt="">text <a href="http://domain.tld">link...</a>

Пример ввода HTML:

<p><a href="http://domain.tld">link here</a> text</p>

Пример вывода с 4 символами:

<p><a href="http://domain.tld">link...</a></p>

Ответы [ 3 ]

1 голос
/ 31 октября 2010

Вот отправная точка, хотя в настоящее время она не содержит никакого кода для обработки требования "Входные теги ограничены: a, img, p, div, span, b, strong"

Itработает, проходя через дочерние узлы узла, и суммируя длину предшествующих братьев и сестер до этой точки.Обратите внимание, что код для получения длины предыдущих родственных элементов требует использования функции набора узлов, которая является функцией расширения до XSLT 1.0.В моем примере я использую функцию Microsoft Extension.

Если узел не является текстовым узлом, общая длина символов до этой точки будет суммой длин предшествующих братьев и сестер, то есть суммапредыдущие родственные элементы родительского узла (который передается в качестве параметра в шаблон).

Вот XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
   <xsl:param name="MAXCHARS">9</xsl:param>

   <xsl:template match="/body">
      <xsl:apply-templates select="child::node()"/>
   </xsl:template>

   <xsl:template match="node()">
      <xsl:param name="LengthToParent">0</xsl:param>

      <!-- Get length of previous siblings -->
      <xsl:variable name="previousSizes">
         <xsl:for-each select="preceding-sibling::node()">
            <length>
               <xsl:value-of select="string-length(.)"/>
            </length>
         </xsl:for-each>
      </xsl:variable>
      <xsl:variable name="LengthToNode" select="sum(msxsl:node-set($previousSizes)/length)"/>

      <!-- Total amount of characters processed so far -->
      <xsl:variable name="LengthSoFar" select="$LengthToNode + number($LengthToParent)"/>

      <!-- Check limit is not exceeded -->
      <xsl:if test="$LengthSoFar &lt; number($MAXCHARS)">
         <xsl:choose>
            <xsl:when test="self::text()">
               <!-- Output text nonde with ... if required -->
               <xsl:value-of select="substring(., 1, number($MAXCHARS) - $LengthSoFar)"/>
               <xsl:if test="string-length(.) &gt; number($MAXCHARS) - $LengthSoFar">...</xsl:if>
            </xsl:when>
            <xsl:otherwise>
               <!-- Output copy of node and recursively call template on its children -->
               <xsl:copy>
                  <xsl:copy-of select="@*"/>
                  <xsl:apply-templates select="child::node()">
                     <xsl:with-param name="LengthToParent" select="$LengthSoFar"/>
                  </xsl:apply-templates>
               </xsl:copy>
            </xsl:otherwise>
         </xsl:choose>
      </xsl:if>
   </xsl:template>

</xsl:stylesheet>

Применительно к этому входу

<body> 
   <img src="image.jpg" alt="" />text <a href="http://domain.tld">link here</a>
</body>

Выход:

<body> 
   <img src="image.jpg" alt="" />text <a href="http://domain.tld">link...</a>
</body>

При применении к этому входу (и изменение параметра на 4 в XSLT)

<p><a href="http://domain.tld">link here</a> text</p>

Выход:

<p><a href="http://domain.tld">link...</a></p>
0 голосов
/ 20 ноября 2012

Как отмечают многие: это становится очень грязным и очень быстрым.Поэтому я просто добавил еще одно поле в БД, в котором есть вводный текст.

0 голосов
/ 31 октября 2010

Эта таблица стилей:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="pMaxLength" select="4"/>
    <xsl:template match="node()">
        <xsl:param name="pPrecedingLength" select="0"/>
        <xsl:variable name="vContent">
            <xsl:copy>
                <xsl:copy-of select="@*"/>
                <xsl:apply-templates select="node()[1]">
                    <xsl:with-param name="pPrecedingLength"
                                    select="$pPrecedingLength"/>
                </xsl:apply-templates>
            </xsl:copy>
        </xsl:variable>
        <xsl:variable name="vLength"
                      select="$pPrecedingLength + string-length($vContent)"/>
        <xsl:if test="$pMaxLength + 3 >= $vLength and
                      (string-length($vContent) or not(node()))">
            <xsl:copy-of select="$vContent"/>
            <xsl:apply-templates select="following-sibling::node()[1]">
                <xsl:with-param name="pPrecedingLength" select="$vLength"/>
            </xsl:apply-templates>
        </xsl:if>
    </xsl:template>
    <xsl:template match="text()" priority="1">
        <xsl:param name="pPrecedingLength" select="0"/>
        <xsl:variable name="vOutput"
                      select="substring(.,1,$pMaxLength - $pPrecedingLength)"/>
        <xsl:variable name="vSumLength"
                      select="$pPrecedingLength + string-length($vOutput)"/>
        <xsl:value-of select="concat($vOutput,
                                     substring('...',
                                               1 div ($pMaxLength
                                                            = $vSumLength)))"/>
        <xsl:apply-templates select="following-sibling::node()[1]">
            <xsl:with-param name="pPrecedingLength"
                            select="$vSumLength"/>
        </xsl:apply-templates>
    </xsl:template>
</xsl:stylesheet>

С этим входом и 9 как pMaxLength:

<html><img src="image.jpg" alt=""/>text <a href="http://domain.tld">link here</a></html>

Вывод:

<html><img src="image.jpg" alt="">text <a href="http://domain.tld">link...</a></html>

И этот входс 4 как pMaxLength:

<html><p><a href="http://domain.tld">link here</a> text</p></html>

Вывод:

<html><p><a href="http://domain.tld">link...</a></p></html>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...