How to extract p tag out of ul tag in xslt

I am trying to transform multiple p tags. If tag has @style then it should be list item otherwise it should just be p tag itself. This is my input:
<blockquote>
<p style="margin-left: 40px;">test</p>
<p style="margin-left: 40px;">some test</p>
<p style="margin-left: 40px;">another test</p>
<p>
<em>paragraph</em>
</p>
<p style="margin-left: 40px;">a</p>
<p style="margin-left: 40px;">b</p>
<p style="margin-left: 40px;">c</p>
<p>
<em>another paragraph</em>
</p>
<p style="margin-left: 40px;">qwert</p>
<p style="margin-left: 40px;">asdf</p>
<p style="margin-left: 40px;">sdfg</p>
<p>
<em>another para</em>
</p>
<p style="margin-left: 40px;">sdfg</p>
<p style="margin-left: 40px;">asdf</p>
<p style="margin-left: 40px;">qwert</p>
And this my xslt template:
<xsl:template match="blockquote">
<xsl:element name="div">
<xsl:attribute name="class" select="'section-content'"/>
<xsl:attribute name="data-class" select="'blockquote'"/>
<xsl:attribute name="data-unlock" select="'ALL'"/>
<xsl:element name="ul">
<xsl:apply-templates/>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template match="blockquote/p[@style]">
<xsl:element name="li">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match="blockquote/p[not(@style)]">
<xsl:element name="p">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
This is output I am getting currently but it is not html5 compliant since p cannot be child of ul tag:
<div class="section-content" data-class="blockquote" data-unlock="ALL">
<ul>
<li>test</li>
<li>some test</li>
<li>another test</li>
<p>
<i>paragraph</i>
</p>
<li>a</li>
<li>b</li>
<li>c</li>
<p>
<i>another paragraph</i>
</p>
<li>qwert</li>
<li>asdf</li>
<li>sdfg</li>
<p>
<i>another para</i>
</p>
<li>sdfg</li>
<li>asdf</li>
<li>qwert</li>
</ul>
What I am trying to get is this markup:
<div class="section-content" data-class="blockquote" data-unlock="ALL">
<ul>
<li>test</li>
<li>some test</li>
<li>another test</li>
</ul>
<p>
<i>paragraph</i>
</p>
<ul>
<li>a</li>
<li>b</li>
<li>c</li>
</ul>
<p>
<i>another paragraph</i>
</p>
<ul>
<li>qwert</li>
<li>asdf</li>
<li>sdfg</li>
</ul>
<p>
<i>another para</i>
</p>
<ul>
<li>sdfg</li>
<li>asdf</li>
<li>qwert</li>
</ul>
To achieve desired output what kind of template rules I should use?
Answer
Seems like a task for for-each-group
group-adjacent
:
<xsl:template match="blockquote">
<div class="section-content" data-class="blockquote" data-unlock="ALL">
<xsl:for-each-group select="*" group-adjacent="boolean(self::p[@style])">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<ul>
<xsl:apply-templates select="current-group()" mode="list-item"/>
</ul>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</div>
</xsl:template>
<xsl:mode name="list-item" on-no-match="shallow-copy"/>
<xsl:template mode="list-item" match="p">
<li>
<xsl:apply-templates mode="#current"/>
</li>
</xsl:template>
<xsl:template match="p/em">
<i>
<xsl:apply-templates/>
</i>
</xsl:template>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output indent="yes"/>
Enjoyed this article?
Check out more content on our blog or follow us on social media.
Browse more articles