xsl-list
[Top] [All Lists]

Re: [xsl] General algorithm for finding nodes between PIs

2017-01-27 08:24:31
I modified my input document slightly:

<?xml version="1.0" encoding="UTF-8"?>
<info>
    <?Fm Condstart VbV-VCO?>
    <p>For this, use <b>that </b>to do that.</p>
    <?Fm Condend VbV-VCO?>
    <p><?Fm Condstart USB?>If you need this, do that.<?Fm Condend USB?></p>
    <p>Outside paragraph.</p>
</info>

Here is how I have implemented Michael's stylesheet:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
        xmlns:xs="http://www.w3.org/2001/XMLSchema";
        exclude-result-prefixes="xs"
        version="2.0">
        
        <xsl:output indent="yes"/>
    
        <xsl:template match="/">
                <results>
                        <xsl:apply-templates/>
                </results>
        </xsl:template>
        
        <xsl:template match="*[processing-instruction('Fm')[starts-with(.,
'Condstart')]]">
                <xsl:for-each-group select="node()"
group-starting-with="processing-instruction('Fm')[starts-with(.,
'Condstart')]">
                        <xsl:if
test="self::processing-instruction('Fm')[starts-with(., 'Condstart')]">
                                <group name="{.}">
                                        <xsl:variable name="pi-end-name"
select="replace(., 'Condstart', 'Condend')"/>
                                        <xsl:for-each-group
select="current-group() except ."
group-ending-with="processing-instruction('Fm')[. = $pi-end-name]">
                                                <xsl:if
test="current-group()[last()][self::processing-instruction('Fm')[. =
$pi-end-name]]">
                                                        <xsl:copy-of
select="current-group()[position() ne last()]"/>
                                                </xsl:if>
                                        </xsl:for-each-group>
                                </group>
                        </xsl:if>
                </xsl:for-each-group>
                <xsl:apply-templates/>
        </xsl:template>
        
        <xsl:template match="text()"/>
        
</xsl:stylesheet>

Here is my output:

<?xml version="1.0" encoding="UTF-8"?>
<results>
   <group name="Condstart VbV-VCO">
      <p>For this, use <b>that </b>to do that.</p>
    </group>
   <group name="Condstart USB">If you need this, do that.</group>
</results>

This is close, but I don't want to lose any elements from the output, like
the parents of the processing instructions (<info>, <p>). Also, I am not
picking up my last <p> element. Thank you for the generous help.

Rick

-----Original Message-----
From: Michael Kay mike(_at_)saxonica(_dot_)com
[mailto:xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com] 
Sent: Thursday, January 26, 2017 5:42 PM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: Re: [xsl] General algorithm for finding nodes between PIs



I think this could be simplified:

<xsl:template match="*[processing-instruction('Fm')[starts-with(.,
'Condstart')]]">
              <xsl:for-each-group select="node()"
group-starting-with="processing-instruction('Fm')[starts-with(.,
'Condstart')]">
                      <xsl:if
test="self::processing-instruction('Fm')[starts-with(., 'Condstart')]">
                              <group name="{.}">
                                      <xsl:variable name="pi-end-name"
select="replace(., 'Condstart', 'Condend')"/>
                                      <xsl:variable name="end"
select="following-sibling::processing-instruction('Fm')[. =
$pi-end-name][1]">
                                      <xsl:copy-of
select="current-group()[. &lt;&lt; $end]"/>
                              </group>
                      </xsl:if>
              </xsl:for-each-group>
              <xsl:apply-templates/>
      </xsl:template>

Michael Kay
Saxonica


Like this:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
      xmlns:xs="http://www.w3.org/2001/XMLSchema";
      exclude-result-prefixes="xs"
      version="2.0">
      
      <xsl:template match="/">
              <results>
                      <xsl:apply-templates/>
              </results>
      </xsl:template>
      
      <xsl:template match="*[processing-instruction('Fm')[starts-with(.,
'Condstart')]]">
              <xsl:for-each-group select="node()"
group-starting-with="processing-instruction('Fm')[starts-with(.,
'Condstart')]">
                      <xsl:if
test="self::processing-instruction('Fm')[starts-with(., 'Condstart')]">
                              <group name="{.}">
                                      <xsl:variable name="pi-end-name"
select="replace(., 'Condstart', 'Condend')"/>
                                      <xsl:for-each-group
select="current-group() except ."
group-ending-with="processing-instruction('Fm')[. = $pi-end-name]">
                                              <xsl:if
test="current-group()[last()][self::processing-instruction('Fm')[. =
$pi-end-name]]">
                                                      <xsl:copy-of
select="current-group()[position() ne last()]"/>
                                              </xsl:if>
                                      </xsl:for-each-group>
                              </group>
                      </xsl:if>
              </xsl:for-each-group>
              <xsl:apply-templates/>
      </xsl:template>
      
      <xsl:template match="text()"/>
      
</xsl:stylesheet>


--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--

<Prev in Thread] Current Thread [Next in Thread>