siddhithakkar 0 Newbie Poster

Hi guys,
I am new to this list and really hope to gain a lot from all the experienced professionals out there.
Here is what I need to do this time around: I have an input code which is a complete flat structure- grouping of elements is desired out of it, and each such element should have an id as well. We have managed to get grouping done but now stuck at the id bit. I would be really grateful if somebody could help.
Aplogies because my code is too lengthy, ideally I would liked them to go as attachments.

Input code:

<p class='Head1'>text1</p>
<p class='Head2'>text2</p>
<p class='Head3'>text3</p>
<p class='Head4'>text4</p>
<p class='Head5'>text5</p>
<p class='Head6'>text6</p>

Current output code:

<sc1>
    <ti>text1</ti>
    <sc2>
       <ti>text2</ti> 
        <sc3>
            <ti>text3</ti>
            <sc4>
                <ti>text4</ti>
                    <sc5>
                        <ti>text5</ti>
                        <sc6>
                            <ti>text6</ti>
                        </sc6>
                    </sc5>
            </sc4>
        </sc3>
    </sc2>
</sc1>

Desired output code:

<sc1 id="1">
    <ti>text1</ti>
    <sc2 id="1-1">
       <ti>text2</ti> 
        <sc3 id="1-1-1">
            <ti>text3</ti>
            <sc4 id="1-1-1-1">
                <ti>text4</ti>
                    <sc5 id="1-1-1-1-1">
                        <ti>text5</ti>
                        <sc6 id="1-1-1-1-1-1">
                            <ti>text6</ti>
                        </sc6>
                    </sc5>
            </sc4>
        </sc3>
    </sc2>
</sc1>

And there are few points to it as well:
1) Multiple elements can appear between <p class="Head__">. They are all required to be nested with the <p class="Head_"> elements appearing before them.
2) Value of Head 1-6 will not always follow the order as shown in the input code above. For instance, Head6 may appear immediately after Head3 and all others might be missing. In that case, the output should be:

<sc1 id="1">
        <sc2 id="1-1">
            <sc3 id="1-1-1">
                <sc4 id="1-1-1-1">
                       <ti>_______</ti>
                        <sc5 id="1-1-1-1-1">
                           <sc6 id="1-1-1-1-1-1">
                                <ti>_____ </ti>
                            </sc6>
                        </sc5>
                </sc4>
            </sc3>
        </sc2>
    </sc1>

3) Id values indicate positions eg: <sc6 id="1-1-1-1-1-1"> signifies <sc6 id="1st occurence of sc1-1st occurence of sc2-1st occurence of sc3-1st occurence of sc4-1st occurence of sc5-1st occurence of sc6"> Hence, when input is:

<p class="Head1">abc</p>
<p class="Head2">def</p>
<p class="Head2">ghi</p>

Output should be:

<sc1 id="1">
    <ti>abc</ti>
    <sc2 id="1-1">
        <ti>def</ti>
      </sc2>
    <sc2 id="1-2">
         <ti>ghi</ti>
    </sc2>
</sc1>

4) My current code is giving a perfect output for grouping, only id values need to be worked upon. Getting some hints to reach there would be really useful. Thanks very much in advance.

Current XSLT code:

<xsl:function name="jsr:group" as="node()*">
  <xsl:param name="elements" as="element()*"/>
  <xsl:param name="level" as="xsd:integer"/>
  <xsl:for-each-group select="$elements" group-starting-with="p[@class=concat('Head',$level)]">
   <xsl:element name="sc{$level}">
    <xsl:attribute name="id">jsr:id($level)</xsl:attribute>
    <xsl:variable name="current-head" as="element()?"
     select="self::p[@class=concat('Head', $level)]"/>
    <xsl:apply-templates select="$current-head"/>
    <xsl:variable name="max-level"
     select="max(for $h in current-group()[self::p[matches(@class,'^Head[0-9]+$')]]
      return xsd:integer(substring($h/@class, 5)))"/>
    <xsl:variable name="next-head" as="element()?"
     select="current-group()/current()/following-sibling::p[matches(@class,'^Head[0-9]+$')][1]"/>
    <xsl:variable name="v1" as="element()*"
     select="following-sibling::*[. &lt;&lt; $next-head]"/>
    <xsl:if test="$level=number(substring-after(@class,'Head'))">
     <xsl:apply-templates select="$v1"/>
    </xsl:if>
    <xsl:choose>
     <xsl:when test="$level &lt; $max-level">
      <xsl:sequence
       select="jsr:group(current-group() except ($current-head, $v1), $level + 1)"
      />
     </xsl:when>
     <xsl:when test="$level=$max-level">
      <xsl:apply-templates select="current-group() except ($current-head, $v1)"/>
     </xsl:when>
     <xsl:otherwise>
      <xsl:apply-templates select="current-group() except $current-head"/>
     </xsl:otherwise>
    </xsl:choose>
   </xsl:element>
  </xsl:for-each-group>
 </xsl:function>
 
 <xsl:template match="div[@class='bdy']">
  <bdy>
   <xsl:variable name="v1" as="element()*"
    select="*[. &lt;&lt; (current()/p[@class='Head1' or @class='Head2' or @class='Head3' or @class='Head4' or @class='Head5' or @class='Head6'])[1]]"/>
   <xsl:apply-templates select="$v1"/>
   <xsl:sequence select="jsr:group(* except $v1, 1)"/>
  </bdy>
 </xsl:template>
 
 <xsl:template match="p[matches(@class, '^Head[0-9]+$')]">
  <ti>
   <xsl:apply-templates/>
  </ti>
 </xsl:template>
 

 <xsl:template match="p[@class='Para_FL']">
  <p>
   <xsl:attribute name="t">fl</xsl:attribute>
   <xsl:apply-templates/>
  </p>
 </xsl:template>
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.