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

Subject: Re: [xsl] General algorithm for finding nodes between PIs
From: "Rick Quatro rick@xxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 27 Jan 2017 15:13:11 -0000
Hi Martin,

That is fantastic, thank you very much! As you can see from my immediately
preceding email, I need something a little different. But with your solution
(which answered the original question), I can run a second pass to get what
I need (as stated in the last email). Thank you again for your generosity.

Rick

-----Original Message-----
From: Martin Honnen martin.honnen@xxxxxx
[mailto:xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx] 
Sent: Friday, January 27, 2017 9:58 AM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] General algorithm for finding nodes between PIs

On 27.01.2017 15:24, Rick Quatro rick@xxxxxxxxxxxxxx wrote:
> 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>

> 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.

Here is an adaption that tries to keep all data and simply replaces any
pi(star/end) pair with a wrapper 'group' element:

<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="@* | node()">
		<xsl:copy>
			<xsl:apply-templates select="@*, node()"/>
		</xsl:copy>
	</xsl:template>

	<xsl:template match="
			*[processing-instruction('Fm')[starts-with(.,
			'Condstart')]]">
		<xsl:copy>
			<xsl:apply-templates select="@*"/>
			<xsl:for-each-group select="node()"
				group-starting-with="
	
processing-instruction('Fm')[starts-with(.,
					'Condstart')]">
				<xsl:choose>
					<xsl:when
test="self::processing-instruction('Fm')[starts-with(.,
'Condstart')]">
						<xsl:variable
name="pi-start-name" as="xs:string" select="."/>
						<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:choose>
								<xsl:when
	
test="
	
current-group()[last()][self::processing-instruction('Fm')[. =
	
$pi-end-name]]">
	
<group name="{$pi-start-name}">
	
<xsl:apply-templates
	
select="current-group()[position() ne last()]"/>
	
</group>
								</xsl:when>
	
<xsl:otherwise>
	
<xsl:apply-templates select="current-group()"/>
	
</xsl:otherwise>
							</xsl:choose>
						</xsl:for-each-group>
					</xsl:when>
					<xsl:otherwise>
						<xsl:apply-templates
select="current-group()"/>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:for-each-group>
		</xsl:copy>
	</xsl:template>

</xsl:stylesheet>

so that gives me

<info>
	<group name="Condstart VbV-VCO">
	<p>For this, use <b>that </b>to do that.</p>
	</group>
	<p><group name="Condstart USB">If you need this, do
that.</group></p>
	<p>Outside paragraph.</p>
</info>

Current Thread