[xsl] Re: AW: AW: global variable and position() once more

Subject: [xsl] Re: AW: AW: global variable and position() once more
From: "Dimitre Novatchev" <dnovatchev@xxxxxxxxx>
Date: Mon, 1 Sep 2003 06:51:50 +0200
This transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kStart"
  match="text()[preceding-sibling::*[1][self::br]]"
  use="contains(., '.')
     and
       number(substring-before(., '.'))
      =
       number(substring-before(., '.'))"/>

  <xsl:key name="kTrail"
  match="text()[preceding-sibling::*[1][self::br]]"
   use="generate-id(
            preceding-sibling::text()
            [
             contains(., '.')
           and
             number(substring-before(., '.'))
            =
             number(substring-before(., '.'))
            ]
            [1]
                   )"/>

  <xsl:template match="/">
    <xsl:for-each select="key('kStart', 'true')">
     <Claim>
      <xsl:copy-of select="normalize-space()"/>
      <xsl:for-each select="key('kTrail', generate-id())">
        <xsl:if test="not(position() = last())">
          <xsl:copy-of
           select="concat(substring(.,1,1),
                          normalize-space(substring(.,2))
                          )"/>
        </xsl:if>
      </xsl:for-each>
     </Claim>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>


when applied on your source.xml:

<html>
  <hr/>   Claims
  <br/>
  <br/>   I claim:
  <br/>
  <br/>   1. blah blah
  <br/>
  <br/>   more blah blah
  <br/>
  <br/>   2. blah blah blah
  <br/>
  <br/>   more blah blah
  <br/>
  <br/>   3. blah blah
  <br/>
  <br/>   more blah blah
  <br/>
  <br/>   4. blah blah blah
  <br/>
  <hr/>   Description
  <br/>
</html>

produces the wanted result:

<Claim>1. blah blah more blah blah</Claim>
<Claim>2. blah blah blah more blah blah</Claim>
<Claim>3. blah blah more blah blah</Claim>
<Claim>4. blah blah blah</Claim>


=====
Cheers,

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

<fe.sola@xxxxxxxxxxxxxx> wrote in message
news:1062365071.3f52678f72c4f@xxxxxxxxxxxxxxxxx
> Hi Markus and all,
> Yep, that template worked fine, now I have a different problem and have
been reading the
> threads of "Incrementing Global variables"... The thing is I have to
select each claim
> on the document and enclose it in <claim></claim>
> The input xhtml file looks like this:
> <hr/>  Claims<br/>
> <br/>  I claim: <br/>
> <br/>  1. blah blah<br/>
> <br/>  more blah blah <br/>
> <br/>  2. blah blah blah  <br/>
>                 <br/>  more blah blah <br/>
> <br/>  3. blah blah<br/>
> <br/>  more blah blah<br/>
> <br/>  4. blah blah blah<br/>
> <hr/>  Description<br/>
> and I need an xml output:
> <Claims>
>     <Claim>1. blah blah more blah blah</Claim>
>     <Claim>2. blah blah blah more blah blah</Claim>
>     <Claim>3. blah blah more blah blah </Claim>
>     <Claim>4. blah blah blah </Claim>
> </Claims>
>
> The number of claims varies from document to document. I thought about
removing the
> <br/> tags with regexps to make things easier...
> What I have so far:
>  <xsl:template
match="preceding-sibling::text()[starts-with(normalize-space
> (.), 'Claims')]
>     and following::text()[starts-with(normalize-space(.), 'Description']">
>                         <xsl:variable name="counter">0</xsl:variable>
>                         <xsl:for-each
select="following-sibling::text()[starts-with
> (normalized-space(.),'$counter+1')]">
>                                     <Claim>
>                                            <xsl:value-of
select="normalize-space(.)"/>
>                                    </Claim>
>                         </xsl:for-each>
> </xsl:template>
> But it gives me error with the Xpath expression due to the variable
increment, what
> should I use, a parameter?
> tia,
> lizet
>
> Mensaje citado por Markus Abt <abt@xxxxxxxx>:
>
> > Hi Lizet,
> >
> > you can use a similar Xpath to check the following sibling axis for
> > checking the end condition and combining the two with "and":
> >
> > <xsl:apply-templates select="html/body/node()[
> >     preceding-sibling::text()[starts-with(normalize-space(.),
'References')]
> >     and following-sibling::text()[starts-with(normalize-space(.),
'Description')]]"/>
> >
> >
> > Cheers,
> > Markus
> > __________________________
> > Markus Abt
> > Comet Computer GmbH
> > http://www.comet.de
> >
> >
> >
> > ----------
> > Von: fe.sola@xxxxxxxxxxxxxx
> > Gesendet: Donnerstag, 28. August 2003 23:02
> > An: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > Betreff: Re: AW: [xsl] global variable and position() once more
> >
> > Hi Markus,
> > It worked fine, thanks. Now I'm doing a similar thing but taking the
text nodes between
> >
> > a text node that starts with 'References' and the text node with
'Description', but
> > it's
> > a similar template...
> > again thanks,
> > lizet
> > Mensaje citado por Markus Abt <abt@xxxxxxxx>:
> >
> > > Hi,
> > >
> > > if you want output everything after the "Description" text node, try
this:
> > >
> > > <?xml version="1.0" encoding="iso-8859-1"?>
> > > <xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
> > >
> > > <xsl:template match="/">
> > >   <Document>
> > >     <!-- select all nodes after the Description text node -->
> > >     <xsl:apply-templates
> > >
select="html/body/node()[preceding-sibling::text()[starts-with(normalize-spa
ce(.),
> > > 'Description')]]"/>
> > >   </Document>
> > > </xsl:template>
> > >
> > > <!-- copy all nodes with their descendants. Adjust to your needs -->
> > > <xsl:template match="@*|node()">
> > >   <xsl:copy>
> > >     <xsl:apply-templates select="@*|node()"/>
> > >   </xsl:copy>
> > > </xsl:template>
> > >
> > > </xsl:stylesheet>
> > >
> > >
> > > The Xpath works as follows:
> > > -  html/body/node() selects all child nodes of the body element.
> > > -  [ ... ] gives a condition to the previous selection.
> > >    It is tested for every selected node.
> > > -  preceding-sibling::text() selects all preceding siblings (for every
selected
> > node
> > > above).
> > > -  starts-with(normalize-space(.), 'Description') tests for the
"Description" text
> > > node.
> > >    It is tested for every preceding sibling.
> > > -  So, preceding-sibling::text()[starts-with(normalize-space(.),
'Description')]
> > >    selects only this node.
> > > -  If there is such a preceding sibling, the outer condition ([...])
is true.
> > > -  The result is, only the html/body/node() with this condition true
are selected.
> > > -  apply-templates then processes this nodes.
> > >
> > > The second template just copies everythig through, discard it, if you
have
> > > your own templates to handle further processing.
> > >
> > >
> > > Hope this helps,
> > > Markus
> > > __________________________
> > > Markus Abt
> > > Comet Computer GmbH
> > > http://www.comet.de
> > >
> > >
> > > ----------
> > > Von: fe.sola@xxxxxxxxxxxxxx
> > > Gesendet: Donnerstag, 28. August 2003 17:53
> > > An: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> > > Betreff: RE: [xsl] global variable and position() once more
> > >
> > > Hello, being a newbie is a pain...
> > > I decided to try Michael Kay's suggestion of using a global variable.
My problem is
> > > that
> > > I need to select the text nodes after a text node that starts with the
> > > word 'Description'.
> > > The xhtml looks more or less like this: (This is a simplified sample
version, could
> >
> > > provide the real one on request)
> > >
> > > <html>
> > >    <head>
> > >       <!--Something here-->
> > >    <head>
> > >    <body>
> > >         blah bla blah
> > >         <table>
> > >           <!-- something here-->
> > >         </table>
> > >         Description
> > >         <table>
> > >           <!-- something here-->
> > >         </table>
> > >         text nodes to select with the description text
> > >
> > >    </body>
> > > </html>
> > >
> > > My xsl stylesheet looks like this:
> > > ..
> > > <xsl:template match="/">
> > >                 ...
> > > <Document>
> > >     <xsl:apply-templates select="html"/>
> > > </Document>
> > >                 ...
> > > </xsl:template>
> > > ..
> > > <xsl:variable name="descPos"
select="//text()[starts-with(normalize-space
> > > (),'Description')]"/>
> > > ..
> > > <xsl:template match="html">
> > >                 <xsl:element name="description">
> > >                        <xsl:apply-templates
select="text()[position()>$descPos]"/>
> > >                 </xsl:element>
> > > ..
> > > </xsl:template>
> > > ..
> > > I can't manage to store in the descPos global variable the position of
the node that
> >
> > > starts with 'Description', when I try
select="//text()[starts-with(normalize-space
> > > (),'Description')position()] or try to get the position function
somewhere in that
> > > XPath
> > > expression I get errors.
> > > So far the descPos variable gets a wrong value, always 1 and the
mentioned text
> > node
> > > has
> > > a position 30 or more on some other input documents.
> > > thanks a lot for looking at this,
> > > Lizet
> > >
> > >
> > >
> > > -------------------------------------------------
> > > Este mensaje fue enviado usando el servicio de correo en web de
Infomed
> > > http://webmail.sld.cu
> > >
> > >  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
> > >
> > >
> > >
> > >  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
> > >
> >
> >
> >
> >
> > -------------------------------------------------
> > Este mensaje fue enviado usando el servicio de correo en web de Infomed
> > http://webmail.sld.cu
> >
> >  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
> >
> >
> >
> >  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
> >
>
>
>
>
> -------------------------------------------------
> Este mensaje fue enviado usando el servicio de correo en web de Infomed
> http://webmail.sld.cu
>
>  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