Я хочу, чтобы xsl приравнял это к следующему: если это подстраница, добавьте к элементу тег ul, а если это последняя подстраница под родителем, добавьте закрывающий тег ul.
Ты думаешь не так. XSLT не пишет теги, он пишет дерево узлов. Вы не можете записать половину узла в дерево результатов.
В XSLT 2.0 вы, вероятно, можете делать то, что вы хотите, используя xsl: for-each-group с атрибутом group-начиная-с - я не могу быть конкретным, потому что вы не указали проблему достаточно четко, но это наверное как то так:
<xsl:template match="parent">
<xsl:for-each-group select="*" group-starting-with="li[....]">
<ul>
<xsl:copy-of select="current-group()"/>
</ul>
</xsl:for-each-group>
</xsl:template>
Если вы застряли с XSLT 1.0, тогда это будет сложнее: я бы использовал технику, называемую «рекурсия брата», в которой вы применяете шаблоны к первому дочернему элементу, который, в свою очередь, применяет шаблоны к следующему брату и скоро. Шаблонное правило для родителя делает это:
<xsl:template match="parent">
<xsl:apply-templates select="*[1]"/>
</xsl:template>
Шаблонное правило для родного брата, который должен быть первым в группе, делает это:
<xsl:template match="parent/*[ (: where this is the first in a group :) ]">
<group>
<xsl:copy-of select="."/>
<xsl:apply-templates select="following-sibling::*[1]"/>
</group>
<xsl:apply-templates select="following-sibling::*[(* start of next group *)][1]"/>
</xsl:template>
и шаблонное правило для других братьев и сестер:
<xsl:template match="parent/*">
<xsl:copy-of select="."/>
<xsl:apply-templates select="following-sibling::*[1]"/>
</xsl:template>
Детали могут быть хитрыми даже для опытных разработчиков XSLT.