Domanda

I'm translating this semi html, semi xml wiki into DITA. My ultimate goal is to achieve nesting of according to h headings. Basically move the nodes after heading nodes(h2 for example) outside of body node, and wrap them with topic/body. The heading level could potentially go down as far as h6.

I saw this post that solves similar problem, but I'm not knowledgeable enough to modify it to close the body tag before other nested elements.

HTML/ XML

<topic id="pageTitle">
   <title>Page Title</title>
   <body>
      <p>some contents.</p>
      <h2>heading title</h2>
      <p>some more content under h heading</p>

      <h3>sub-heading title</h3>
      <p>some more content under sub heading</p>
      <p>some more content under sub heading</p>

      <h2>heading title</h2>
      <p>some more content under h heading</p>
   </body>
</topic>

I want to achieve nesting in DITA

<topic id="pageTitle">
   <title>Page Title</title>
   <body>
      <p>some contents.</p>
   </body>

   <topic id="headingtitle">
      <title>heading title</title>
      <body>
         <p>some more content under h heading</p>
      </body>

      <topic id="sub-headingtitle">
         <title>sub-heading title</title>
         <body>
            <p>some more content under sub heading</p>
            <p>some more content under sub heading</p>
         </body>
      </topic>
   </topic>

   <topic id="headingtitle">
      <title>heading title</title>
      <body>
         <p>some more content under h heading</p>
      </body>
   </topic>
</topic>

Please note: the <body> tag is closed before the other topic begin. This is standard of DITA, that topic must not nest inside body of another topic.

Also, if the body node is followed immediately with a heading node, then body node will be removed.

For example, XML

<topic id="pageTitle">
   <title>Page Title</title>
   <body>
      <h2>heading title</h2>
      <p>some more content under h heading</p>
   </body>
</topic>

Goal

<topic id="pageTitle">
   <title>Page Title</title>

   <topic id="headingtitle">
      <title>h2 heading</title>
      <body>
         <p>some more content under h heading</p>
      </body>
   </topic>

</topic>
È stato utile?

Soluzione

Here is my suggestion using XSLT 2.0 and for-each-group group-starting-with in a recursive function:

<xsl:stylesheet
  version="2.0"
  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="xs mf">

<xsl:output indent="yes"/>

<xsl:function name="mf:get-id-sub" as="xs:string">
  <xsl:param name="level" as="xs:integer"/>
  <xsl:sequence select="string-join(for $i in 3 to $level return 'sub-', '')"/>
</xsl:function>

<xsl:function name="mf:group" as="element()*">
  <xsl:param name="elements" as="element()*"/>
  <xsl:param name="level" as="xs:integer"/>
  <xsl:for-each-group select="$elements" group-starting-with="*[local-name() eq concat('h', $level)]">
    <xsl:choose>
      <xsl:when test="not(self::*[local-name() eq concat('h', $level)])">
        <body>
          <xsl:apply-templates select="current-group()"/>
        </body>
      </xsl:when> 
      <xsl:otherwise>
        <topic id="{mf:get-id-sub($level)}headingtitle">
          <xsl:apply-templates select="."/>
          <xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
        </topic>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:for-each-group>
</xsl:function>

<xsl:template match="@* | node()">
  <xsl:copy>
    <xsl:apply-templates select="@* , node()"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="topic[@id = 'pageTitle']/body">
  <xsl:sequence select="mf:group(*, 2)"/>
</xsl:template>

<xsl:template match="h2 | h3 | h4 | h5 | h6">
  <title>
    <xsl:apply-templates/>
  </title>
</xsl:template>

</xsl:stylesheet>

It transforms

<topic id="pageTitle">
   <title>Page Title</title>
   <body>
      <h2>heading title</h2>
      <p>some more content under h heading</p>
   </body>
</topic>

into

<topic id="pageTitle">
   <title>Page Title</title>
   <topic id="headingtitle">
      <title>heading title</title>
      <body>
         <p>some more content under h heading</p>
      </body>
   </topic>
</topic>

and

<topic id="pageTitle">
   <title>Page Title</title>
   <body>
      <p>some contents.</p>
      <h2>heading title</h2>
      <p>some more content under h heading</p>

      <h3>sub-heading title</h3>
      <p>some more content under sub heading</p>
      <p>some more content under sub heading</p>

      <h2>heading title</h2>
      <p>some more content under h heading</p>
   </body>
</topic>

into

<topic id="pageTitle">
   <title>Page Title</title>
   <body>
      <p>some contents.</p>
   </body>
   <topic id="headingtitle">
      <title>heading title</title>
      <body>
         <p>some more content under h heading</p>
      </body>
      <topic id="sub-headingtitle">
         <title>sub-heading title</title>
         <body>
            <p>some more content under sub heading</p>
            <p>some more content under sub heading</p>
         </body>
      </topic>
   </topic>
   <topic id="headingtitle">
      <title>heading title</title>
      <body>
         <p>some more content under h heading</p>
      </body>
   </topic>
</topic>
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top