Re: [xsl] Nesting a flat XML structure

Subject: Re: [xsl] Nesting a flat XML structure
From: "Martin Honnen martin.honnen@xxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Mon, 29 Oct 2018 18:52:51 -0000
On 29.10.2018 19:14, ian.proudfoot@xxxxxxxxxxx wrote:


I tried to create a recursive template to do the work, but thats where I got stuck.

Here is some recursion example:


<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
	xmlns:xs="http://www.w3.org/2001/XMLSchema";
	xmlns:mf="http://example.com/mf";
	exclude-result-prefixes="#all"
	version="3.0">

  <xsl:param name="header-prefix" as="xs:string" select="'h'"/>
  <xsl:param name="list-prefix" as="xs:string">bullet_level</xsl:param>

<xsl:function name="mf:group" as="node()*">
<xsl:param name="elements" as="element()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$elements" group-starting-with="*[@style = $header-prefix || $level]">
<xsl:choose>
<xsl:when test="self::*[@style = $header-prefix || $level]">
<section>
<title>
<xsl:apply-templates/>
</title>
<xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
</section>
</xsl:when>
<xsl:otherwise>
<xsl:for-each-group select="current-group()" group-adjacent="boolean(self::*[starts-with(@style, $list-prefix)])">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:sequence select="mf:list-group(current-group(), 1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>


<xsl:function name="mf:list-group" as="node()*">
<xsl:param name="elements" as="element()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:where-populated>
<ul>
<xsl:for-each-group select="$elements" group-starting-with="*[@style = $list-prefix || $level]">
<li>
<xsl:apply-templates/>
<xsl:sequence select="mf:list-group(current-group() except ., $level + 1)"/>
</li>
</xsl:for-each-group>
</ul>
</xsl:where-populated>
</xsl:function>


  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="doc">
      <xsl:copy>
          <xsl:sequence select="mf:group(*, 1)"/>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="p[@style = 'para']">
      <p>
          <xsl:apply-templates/>
      </p>
  </xsl:template>

</xsl:stylesheet>

Outputs (https://xsltfiddle.liberty-development.net/eiZQaG9)

<doc>
   <section>
      <title>title text</title>
      <p>body text</p>
      <p>body text</p>
      <ul>
         <li>list text</li>
         <li>list text<ul>
               <li>list text</li>
               <li>list text</li>
               <li>list text</li>
            </ul>
         </li>
      </ul>
      <section>
         <title>title text</title>
         <p>body text</p>
         <p>body text</p>
      </section>
   </section>
</doc>

though so keeps the "ul" lists separated from the sibling "p" elements, have so far not understood why a list belongs into a preceding paragraph.

Current Thread