[xsl] Re: Selecting the first sentence of a paragraph

Subject: [xsl] Re: Selecting the first sentence of a paragraph
From: "Dimitre Novatchev" <dnovatchev@xxxxxxxxx>
Date: Tue, 28 Oct 2003 09:06:43 +0100
This transformation:

<xsl:stylesheet version="1.0"

 <xsl:output omit-xml-declaration="yes"/>

  <xsl:template match="/">
    <xsl:apply-templates select="p" mode="fstSent"/>

  <xsl:template match="@* | node()" mode="fstSent">
      <xsl:when test="not(self::p)
                        [contains(., '.')]"/>

      <xsl:when test="self::text()[contains(., '.')]">
        select="concat(substring-before(., '.'), '.')"/>
          <xsl:apply-templates select="@* | node()"


when applied on this source xml (a complicated variant of the one originally

<p> Identical
  <u>and similar</u>
   The optional argument
  <arg> n</arg> specifies the level of detail.

produces the wanted result:

<p> Identical
  <u>and similar</u>


Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL

"Larry Kollar" <kollar@xxxxxxxxxx> wrote in message
> Subject says it mostly, but I want to include any elements as well as
> text nodes making up that first sentence.
> Hm, maybe I'd better show a sample XML fragment:
> <section>
>    <label>show exception</label>
>    <p>Syntax: <cmd>show exception <arg>n</arg></cmd></p>
>    <p>Identical to <keyword>systat</keyword>.
>    The optional argument <arg>n</arg> specifies the level of detail.</p>
>    <other>stuff we don't care about</other>
> </section>
> The part I have working pretty well applies the identity transform to
> the first paragraph if it starts with "Syntax." I also want to copy the
> first sentence of the next paragraph (or the first sentence of the first
> paragraph if there's no "Syntax" definition). The following template
> gets the first sentence but removes the internal markup:
> <xsl:template match="p" mode="firstsentence">
> <p><xsl:copy-of select='concat(substring-before(.,"."), ".")' /></p>
> </xsl:template>
> Producing "Identical to systat." That I expect, and set it up as a
> placeholder until I could get what I really wanted. That's been
> somewhat knottier.
> I assume I'll have to use xsl:for-each to select all the nodes up
> to the first period in the paragraph, apply the identity transform
> to them, then select the node containing the period and use the
> concat(substring-before(.,"."),".") function to get that part.
> I've tried a couple of variations on
> xsl:for-each select='./*/preceding-sibling::*[contains(text(),".")]'
> which is probably causing hysterical laughter and/or retching
> among some of you.... I'm probably making this harder than it
> has to be.
> Any suggestions are much appreciated. I'm using xsltproc if
> that makes a difference.
> --
> Larry Kollar    k  o  l  l  a  r  @  a  l  l  t  e  l  .  n  e  t
> "The hardest part of all this is the part that requires thinking."
> -- Paul Tyson, on xml-doc
>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list

Current Thread