Простая проблема группировки в XSLT 2 или 3:
<xsl:template match="/*">
<xsl:for-each-group select="descendant::*" group-starting-with="container">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="current-group() except ." mode="copy"/>
</xsl:copy>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="*" mode="copy">
<xsl:copy/>
</xsl:template>
Полный пример https://xsltfiddle.liberty -development.net / bdxtqQ :
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/*">
<xsl:for-each-group select="descendant::*" group-starting-with="container">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="current-group() except ." mode="copy"/>
</xsl:copy>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="*" mode="copy">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
Asдля редактирования наличия элементов, предшествующих первому container
, который вы не хотите выводить, измените шаблон, выполняющий группировку, на
<xsl:template match="/*">
<xsl:for-each-group select="descendant::*" group-starting-with="container">
<xsl:if test="self::container">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="current-group() except ." mode="copy"/>
</xsl:copy>
</xsl:if>
</xsl:for-each-group>
</xsl:template>
https://xsltfiddle.liberty -development.net / bdxtqQ /1
Принцип работы for-each-group group-starting-with
(см. https://www.w3.org/TR/xslt-30/#element-for-each-group) заключается в том, что если первый элемент в группе не соответствует шаблону group-starting-with
, он, тем не менее, образует группу:
Если присутствует атрибут group-начиная-с, то его значение должно быть шаблоном.
Элементы в совокупности проверяются в порядке заполнения. Если элемент соответствует шаблону, или является первым элементом в совокупности, затем создается новая группа, и элемент становится его первым членом. В противном случае элемент добавляется в ту же группу, что и предыдущий элемент в совокупности.
Это полезно во многих случаях, но часто требуетo использовать вложенный xsl:if
или xsl:choose
внутри xsl:for-each-group
, который проверяет, есть ли у нас "настоящая" группа, соответствующая шаблону group-starting-with
, или мы только что собрали какие-либо элементы перед первой такой группой.