A selection of abstracts from n words, including HTML tags with XSLT

I want to select an abstract along with HTML format elements using XSLT. Here is an example XML:

<PUBLDES>The <IT>European Journal of Cancer (including EJC Supplements),</IT> 
is an international comprehensive oncology journal that publishes original 
research, editorial comments, review articles and news on experimental oncology, 
clinical oncology (medical, paediatric, radiation, surgical), translational 
oncology, and on cancer epidemiology and prevention. The Journal now has online
submission for authors. Please submit manuscripts at 
<SURL>http://ees.elsevier.com/ejc</SURL> and follow the instructions on the 
site.<P/>

The <IT>European Journal of Cancer (including EJC Supplements)</IT> is the 
official Journal of the European Organisation for Research and Treatment 
of Cancer (EORTC), the European CanCer Organisation (ECCO), the European 
Association for Cancer Research (EACR), the the European Society of Breast 
Cancer Specialists (EUSOMA) and the European School of Oncology (ESO). <P/>
Supplements to the <IT>European Journal of Cancer</IT> are published under 
the title <IT>EJC Supplements</IT> (ISSN 1359-6349).  All subscribers to 
<IT>European Journal of Cancer</IT> automatically receive this publication.<P/>
To access the latest tables of contents, abstracts and full-text articles 
from <IT>EJC</IT>, including Articles-in-Press, please visit <URL>
<HREF>http://www.sciencedirect.com/science/journal/09598049</HREF>
<HTXT>ScienceDirect</HTXT>
</URL>.</PUBLDES>

How can I say 45 words from it, as well as HTML tags in it. When I use substring()or concat(), it removes the tags (e.g., <IT>etc.).

+3
source share
1 answer

You probably would be better off doing this programmatically rather than with pure XSLT, but if you need to use XSLT, here is one way to do this. It includes several style sheets, although if you could use extension functions, you can use node-sets and combine them into one large (and nasty) style sheet.

XML, "tokenise" , , "WORD".

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <!-- Copy existing nodes and attributes -->
   <xsl:template match="@*|node()">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>
   <!-- Match text nodes -->
   <xsl:template match="text()">
      <xsl:call-template name="tokenize">
         <xsl:with-param name="string" select="."/>
      </xsl:call-template>
   </xsl:template>
   <!-- Splits a string into separate elements for each word -->
   <xsl:template name="tokenize">
      <xsl:param name="string"/>
      <xsl:param name="delimiter" select="' '"/>
      <xsl:choose>
         <xsl:when test="$delimiter and contains($string, $delimiter)">
            <xsl:variable name="word" select="normalize-space(substring-before($string, $delimiter))"/>
            <xsl:if test="string-length($word) &gt; 0">
               <WORD>
                  <xsl:value-of select="$word"/>
               </WORD>
            </xsl:if>
            <xsl:call-template name="tokenize">
               <xsl:with-param name="string" select="substring-after($string, $delimiter)"/>
               <xsl:with-param name="delimiter" select="$delimiter"/>
            </xsl:call-template>
         </xsl:when>
         <xsl:otherwise>
            <xsl:variable name="word" select="normalize-space($string)"/>
            <xsl:if test="string-length($word) &gt; 0">
               <WORD>
                  <xsl:value-of select="$word"/>
               </WORD>
            </xsl:if>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>
</xsl:stylesheet>

XSLT, "tokenize" , :

tokenizing-and-sorting-with-xslt-1-0

( , XSLT2.0 , , )

XML, ...

<PUBLDES>
   <WORD>The</WORD>
   <IT>
      <WORD>European</WORD>
      <WORD>Journal</WORD>
      <WORD>of</WORD>
      ....

...

, XML, XSLT, 45 . , . node

  • WORD. . , .
  • , . , .
  • , . node ( ) .

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:variable name="WORDCOUNT">6</xsl:variable>

   <!-- Match root element -->
   <xsl:template match="/">
      <xsl:apply-templates select="descendant::*[1]" mode="word">
         <xsl:with-param name="previousWords">0</xsl:with-param>
      </xsl:apply-templates>
   </xsl:template>

   <!-- Match any node -->
   <xsl:template match="node()" mode="word">
      <xsl:param name="previousWords"/>

      <!-- Number of words below the element (at any depth) -->
      <xsl:variable name="childWords" select="count(descendant::WORD)"/>
      <xsl:choose>
         <!-- Matching a WORD element -->
         <xsl:when test="local-name(.) = 'WORD'">
            <!-- Copy the word -->
            <WORD>
               <xsl:value-of select="."/>
            </WORD>
            <!-- If there are still words to output, continue processing at next sibling -->
            <xsl:if test="$previousWords + 1 &lt; $WORDCOUNT">
               <xsl:apply-templates select="following-sibling::*[1]" mode="word">
                  <xsl:with-param name="previousWords">
                     <xsl:value-of select="$previousWords + 1"/>
                  </xsl:with-param>
               </xsl:apply-templates>
            </xsl:if>
         </xsl:when>

         <!-- Match a node where the number of words below it is within allowed limit -->
         <xsl:when test="$childWords &lt;= $WORDCOUNT - $previousWords">
            <!-- Copy the element -->
            <xsl:copy>
               <!-- Copy all its desecendants -->
               <xsl:copy-of select="*|@*"/>
            </xsl:copy>
            <!-- If there are still words to output, continue processing at next sibling -->
            <xsl:if test="$previousWords + $childWords &lt; $WORDCOUNT">
               <xsl:apply-templates select="following-sibling::*[1]" mode="word">
                  <xsl:with-param name="previousWords">
                     <xsl:value-of select="$previousWords + $childWords"/>
                  </xsl:with-param>
            </xsl:apply-templates>
         </xsl:if>
         </xsl:when>

         <!-- Match nodes where the number of words below it would exceed current limit -->
         <xsl:otherwise>
            <!-- Copy the node -->
            <xsl:copy>
               <!-- Continue processing at very first child node -->
               <xsl:apply-templates select="descendant::*[1]" mode="word">
                  <xsl:with-param name="previousWords">
                     <xsl:value-of select="$previousWords"/>
                  </xsl:with-param>
               </xsl:apply-templates>
            </xsl:copy>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>
</xsl:stylesheet>

4 , ,

<PUBLDES>
   <WORD>The</WORD>
   <IT>
      <WORD>European</WORD>
      <WORD>Journal</WORD>
      <WORD>of</WORD>
   </IT>
</PUBLDES>

, WORD . ....

, , !

+4

Source: https://habr.com/ru/post/1730170/


All Articles