I have a sample xsl like this,
<doc>
<p type="para">aaxx</p>
<p type="paraX">aaxx</p>
<p type="paraX">aaxx</p>
<context type="para">aaxx</context>
<p type="paraX">aaxx</p>
<s>jksjdl</s>
<p type="para">bbcc</p>
<p type="paraX">kkll</p>
<p type="paraX">aaxx</p>
<p type="paraX">aaxx</p>
<p type="paraX">aaxx</p>
<p type="paraX">aaxx</p>
<k>text</k>
<p type="para">bbcc</p>
<p type="paraX">aaxx</p>
<p type="paraX">aaxx</p>
<context type="para">aaxx</context>
<p type="paraX">kkll</p>
<t>text</t>
<p type="paraX">aa</p>
<p type="paraX">kddkll</p>
</doc>
My requirment is,
search for any <p type="para">
followed by any combination of p
with a type starting with paraX
and of <context type="para”>
and insert that content into a <section>
.
So, My expected output should look like,
<doc>
<section>
<p type="para">aaxx</p>
<p type="paraX">aaxx</p>
<p type="paraX">aaxx</p>
<context type="para">aaxx</context>
<p type="paraX">aaxx</p>
</section>
<s>jksjdl</s>
<section>
<p type="para">bbcc</p>
<p type="paraX">kkll</p>
<p type="paraX">aaxx</p>
<p type="paraX">aaxx</p>
<p type="paraX">aaxx</p>
<p type="paraX">aaxx</p>
</section>
<k>text</k>
<section>
<p type="para">bbcc</p>
<p type="paraX">aaxx</p>
<p type="paraX">aaxx</p>
<context type="para">aaxx</context>
<p type="paraX">kkll</p>
</section>
<t>text</t>
<p type="paraX">aa</p>
<p type="paraX">kddkll</p>
</doc>
I've written following XSLT to do that,
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p[@type='para']"/>
<xsl:template match="p[@type='paraX']"/>
<xsl:template match="p[@type='para']">
<section>
<p type="para">
<xsl:apply-templates/>
</p>
<xsl:apply-templates select="following-sibling::*[1]" mode="box"/>
</section>
</xsl:template>
<xsl:template match="p" mode="box">
<p type="{@type}">
<xsl:apply-templates/>
</p>
<xsl:apply-templates select="following-sibling::p[1][@type='paraX'] | following-sibling::context[1][@type='para']" mode="box"/>
</xsl:template>
<xsl:template match="context" mode="box">
<context type="{@type}">
<xsl:apply-templates/>
</context>
<xsl:apply-templates select="following-sibling::p[1][@type='paraX'] | following-sibling::context[1][@type='para']" mode="box"/>
</xsl:template>
But it gives the following output,
<doc>
<section>
<p type="para">aaxx</p>
<p type="paraX">aaxx</p>
<p type="paraX">aaxx</p>
<context type="para">aaxx</context>
<p type="paraX">aaxx</p>
<context type="para">aaxx</context>
<p type="paraX">kkll</p>
<context type="para">aaxx</context>
<p type="paraX">kkll</p>
<p type="paraX">aaxx</p>
<context type="para">aaxx</context>
<p type="paraX">kkll</p>
<context type="para">aaxx</context>
<p type="paraX">aaxx</p>
<context type="para">aaxx</context>
<p type="paraX">kkll</p>
<context type="para">aaxx</context>
<p type="paraX">kkll</p>
</section>
<context type="para">aaxx</context>
<s>jksjdl</s>
<section>
<p type="para">bbcc</p>
<p type="paraX">kkll</p>
<p type="paraX">aaxx</p>
<p type="paraX">aaxx</p>
<p type="paraX">aaxx</p>
<p type="paraX">aaxx</p>
<context type="para">aaxx</context>
<p type="paraX">kkll</p>
<context type="para">aaxx</context>
<p type="paraX">kkll</p>
<context type="para">aaxx</context>
<p type="paraX">kkll</p>
<context type="para">aaxx</context>
<p type="paraX">kkll</p>
<context type="para">aaxx</context>
<p type="paraX">kkll</p>
</section>
<k>text</k>
<section>
<p type="para">bbcc</p>
<p type="paraX">aaxx</p>
<p type="paraX">aaxx</p>
<context type="para">aaxx</context>
<p type="paraX">kkll</p>
<p type="paraX">kkll</p>
<context type="para">aaxx</context>
<p type="paraX">kkll</p>
</section>
<context type="para">aaxx</context>
</doc>
Any idea how can I modify my templates to get the correct output?
You haven't specified the requirements clearly enough to be certain of getting the code right, but for the supplied input, the following would work:
<xsl:template match="doc">
<doc>
<xsl:for-each-group select="*"
group-starting-with="p[@type='para'] | *[not(self::p | self::context)]">
<xsl:choose>
<xsl:when test="self::p">
<section><xsl:copy-of select="current-group()"/></section>
<xsl:when>
<xsl:otherwise>
<xsl:copy-of select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</doc>
</xsl:template>
I'm sure your approach using sibling recursion can be made to work, but personally I find positional grouping with for-each-group much clearer and easier to debug.