xsl-list
[Top] [All Lists]

Re: [xsl] Nesting a flat XML structure

2018-10-29 13:52:57
On 29.10.2018 19:14, ian(_dot_)proudfoot(_at_)itp-x(_dot_)co(_dot_)uk wrote:


I tried to create a recursive template to do the work, but that’s 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.
--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--

<Prev in Thread] Current Thread [Next in Thread>