I'm having multiple topics, I need to include section tag along with the Topic element with numbering ID's
My Input XML is:
<Article>
<Title>Mam</Title>
<Items>
<Item>
<Name>cyst1?</Name>
<Body>
<h1>aaa</h1><p>knee1.</p>
<h2>bbb</h2><p>knee2.</p>
</Body>
</Item>
<Item>
<Name>cyst2?</Name>
<Body>
<p>knee3.</p>
</Body>
</Item>
</Items>
XSL I Used as:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="#all">
<xsl:template match="Article">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="Title"/>
<xsl:template match="h1"/>
<xsl:template match="h2"/>
<xsl:template match="Items">
<xsl:for-each-group select="*" group-starting-with="Items">
<topic>
<xsl:attribute name="id">topic_Head<xsl:number count="Items | Item"/>
</xsl:attribute>
<title>
<xsl:value-of select="//Title"/>
</title>
<xsl:for-each-group select="current-group()" group-starting-with="Item">
<xsl:choose>
<xsl:when test="self::Item">
<topic>
<xsl:attribute name="id">topic_<xsl:number count="Items | Item"/>
</xsl:attribute>
<xsl:apply-templates select="node()"/>
</topic>
</xsl:when>
<xsl:otherwise>
<body>
<xsl:apply-templates select="current-group()"/>
</body>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</topic>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="Body">
<body>
<xsl:apply-templates/>
</body>
</xsl:template>
<xsl:template match="p">
<p>
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="Name">
<title>
<xsl:apply-templates/>
</title>
</xsl:template>
Output I got as:
<topic id="topic_1">
<title>Mam</title>
<topic id="topic_2">
<title>cyst1?</title>
<body>
<p>knee1.</p><p>knee2.</p>
</body>
</topic>
<topic id="topic_3">
<title>cyst2?</title>
<body>
<p>knee3.</p>
</body>
</topic>
Expected Output:
<topic id="topic_1">
<title>Mam</title>
<topic id="topic_2">
<title>cyst1?</title>
<body>
<section id="section1">
<title>aaa</title><p>knee1.</p>
<section id="section2">
<title>bbb</title><p>knee2.</p>
</section>
</section>
</body>
</topic>
<topic id="topic_3">
<title>cyst2?</title>
<body>
<p>knee3.</p>
</body>
</topic>
I need the h1 and h2 come as section with Id attribute and close as per the header order.
Please suggest me coding on this. Thanks in advance.
Following styleshhet will work.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:ahf="http://www.antennahouse.com/names/XSLT/Functions/Document"
exclude-result-prefixes="#all">
<xsl:output method="xml" indent="yes" omit-xml-declaration="no"/>
<xsl:strip-space elements="*"/>
<xsl:template match="Article">
<topic>
<xsl:attribute name="id" select="ahf:genTopicId(.)"/>
<xsl:apply-templates/>
</topic>
</xsl:template>
<xsl:template match="Title">
<title>
<xsl:apply-templates/>
</title>
</xsl:template>
<xsl:template match="Items">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="Item">
<topic>
<xsl:attribute name="id" select="ahf:genTopicId(.)"/>
<xsl:apply-templates/>
</topic>
</xsl:template>
<xsl:template match="Name">
<title>
<xsl:apply-templates/>
</title>
</xsl:template>
<xsl:template match="Body">
<body>
<xsl:call-template name="groupBody">
<xsl:with-param name="prmBodyElem" select="*"/>
</xsl:call-template>
</body>
</xsl:template>
<xsl:template name="groupBody">
<xsl:param name="prmBodyElem" as="element()*"/>
<xsl:variable name="maxHn" as="xs:integer" select="ahf:getMaxHn($prmBodyElem)"/>
<xsl:choose>
<xsl:when test="$maxHn eq $notHn">
<xsl:apply-templates select="$prmBodyElem"/>
</xsl:when>
<xsl:otherwise>
<xsl:for-each-group select="$prmBodyElem" group-adjacent="ahf:genGroupNo(.,$maxHn,$prmBodyElem)">
<xsl:choose>
<xsl:when test="current-grouping-key() eq 0">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<section>
<xsl:attribute name="id" select="ahf:genSectionId(current-group()[1])"/>
<title>
<xsl:apply-templates select="./node()"/>
</title>
<xsl:call-template name="groupBody">
<xsl:with-param name="prmBodyElem" select="subsequence(current-group(),2)"/>
</xsl:call-template>
</section>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:variable name="notHn" as="xs:integer" select="9999"/>
<xsl:function name="ahf:getMaxHn" as="xs:integer">
<xsl:param name="prmElem" as="element()+"/>
<xsl:variable name="hn" as="xs:integer*">
<xsl:for-each select="$prmElem">
<xsl:choose>
<xsl:when test="matches(name(),'h[1-9]')">
<xsl:sequence select="xs:integer(substring(name(),2))"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="$notHn"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
<xsl:sequence select="min($hn)"/>
</xsl:function>
<xsl:template match="p">
<p>
<xsl:apply-templates/>
</p>
</xsl:template>
<!-- Generate id number for topic -->
<xsl:function name="ahf:genTopicId" as="xs:string">
<xsl:param name="prmElem" as="element()"/>
<xsl:sequence select="concat('topic_',count($prmElem|root($prmElem)//*[self::Article or self::Item][. << $prmElem]))"/>
</xsl:function>
<!-- Grouping by hN (N = $prmMaxHn)
0: not h1, h2, h3...
> 1: hN group
-->
<xsl:function name="ahf:genGroupNo" as="xs:integer">
<xsl:param name="prmElem" as="element()"/>
<xsl:param name="prmMaxHn" as="xs:integer"/>
<xsl:param name="prmRange" as="element()*"/>
<xsl:variable name="GroupHn" as="xs:string" select="concat('h',$prmMaxHn)"/>
<xsl:sequence select="count($prmElem[self::*[name() eq $GroupHn]]) + count($prmElem/preceding-sibling::*[name() eq $GroupHn][(. is $prmRange[1]) or (. >> $prmRange[1])])"/>
</xsl:function>
<!--Generate id number for section -->
<xsl:function name="ahf:genSectionId" as="xs:string">
<xsl:param name="prmElem" as="element()"/>
<xsl:sequence select="concat('section_',count($prmElem|$prmElem/preceding::*[matches(name(),'h[1-9]')]))"/>
</xsl:function>
</xsl:stylesheet>
[The result]
<?xml version="1.0" encoding="UTF-8"?>
<topic id="topic_1">
<title>Mam</title>
<topic id="topic_2">
<title>cyst1?</title>
<body>
<section id="section_1">
<title>aaa</title>
<p>knee1.</p>
<section id="section_2">
<title>bbb</title>
<p>knee2.</p>
</section>
</section>
</body>
</topic>
<topic id="topic_3">
<title>cyst2?</title>
<body>
<p>knee3.</p>
</body>
</topic>
</topic>
I'm still afraid if the expected result is DITA topic instance, nesting section element is not allowed.