0
votes

Hello i try to fix the nested list elements in XSLT 2.0,transformation to HTML and my XML is like above;

<w:p w:rsidR="008845A9" w:rsidRPr="001509B0" w:rsidRDefault="008845A9" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
    </w:pPr>
</w:p>
<w:p w:rsidR="001207E2" w:rsidRPr="001509B0" w:rsidRDefault="001207E2" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
        <w:numPr>
            <w:ilvl w:val="1"/>
            <w:numId w:val="5"/>
        </w:numPr>
    </w:pPr>
    <w:r w:rsidRPr="001509B0">
        <w:t>First Item</w:t>
    </w:r>
</w:p>
<w:p w:rsidR="00AD36E6" w:rsidRPr="001509B0" w:rsidRDefault="00AD36E6" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
        <w:numPr>
            <w:ilvl w:val="1"/>
            <w:numId w:val="5"/>
        </w:numPr>
    </w:pPr>
    <w:r w:rsidRPr="001509B0">
        <w:t>Second Item</w:t>
    </w:r>
</w:p>
<w:p w:rsidR="00AD36E6" w:rsidRPr="001509B0" w:rsidRDefault="00AD36E6" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
        <w:numPr>
            <w:ilvl w:val="1"/>
            <w:numId w:val="5"/>
        </w:numPr>
    </w:pPr>
    <w:r w:rsidRPr="001509B0">
        <w:t>Third Item</w:t>
    </w:r>
</w:p>
<w:p w:rsidR="002B7A91" w:rsidRPr="001509B0" w:rsidRDefault="002B7A91" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
        <w:numPr>
            <w:ilvl w:val="2"/>
            <w:numId w:val="5"/>
        </w:numPr>
    </w:pPr>
    <w:r w:rsidRPr="001509B0">
        <w:t>Third Item – One</w:t>
    </w:r>
</w:p>
<w:p w:rsidR="002B7A91" w:rsidRPr="001509B0" w:rsidRDefault="002B7A91" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
        <w:numPr>
            <w:ilvl w:val="2"/>
            <w:numId w:val="5"/>
        </w:numPr>
    </w:pPr>
    <w:r w:rsidRPr="001509B0">
        <w:t xml:space="preserve">Third Item </w:t>
    </w:r>
    <w:r w:rsidR="006551A3" w:rsidRPr="001509B0">
        <w:t>–</w:t>
    </w:r>
    <w:r w:rsidRPr="001509B0">
        <w:t xml:space="preserve"> Two</w:t>
    </w:r>
</w:p>
<w:p w:rsidR="006551A3" w:rsidRPr="001509B0" w:rsidRDefault="006551A3" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
        <w:numPr>
            <w:ilvl w:val="3"/>
            <w:numId w:val="6"/>
        </w:numPr>
    </w:pPr>
    <w:r w:rsidRPr="001509B0">
        <w:t xml:space="preserve">Sample Item </w:t>
    </w:r>
    <w:r w:rsidR="00554D9D" w:rsidRPr="001509B0">
        <w:t>A</w:t>
    </w:r>
</w:p>
<w:p w:rsidR="006551A3" w:rsidRPr="001509B0" w:rsidRDefault="00554D9D" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
        <w:numPr>
            <w:ilvl w:val="3"/>
            <w:numId w:val="6"/>
        </w:numPr>
    </w:pPr>
    <w:r w:rsidRPr="001509B0">
        <w:t>Sample Item B</w:t>
    </w:r>
</w:p>
<w:p w:rsidR="002B7A91" w:rsidRPr="001509B0" w:rsidRDefault="002B7A91" w:rsidP="004E414C">
    <w:pPr>
        <w:pStyle w:val="AppBody-Description"/>
        <w:numPr>
            <w:ilvl w:val="1"/>
            <w:numId w:val="5"/>
        </w:numPr>
    </w:pPr>
    <w:r w:rsidRPr="001509B0">
        <w:t>Fo</w:t>
    </w:r>
    <w:r w:rsidR="00565721" w:rsidRPr="001509B0">
        <w:t>u</w:t>
    </w:r>
    <w:r w:rsidRPr="001509B0">
        <w:t>rth Item</w:t>
    </w:r>
</w:p>

And the full XSLT

<xsl:output method="html" doctype-system="about:legacy-compat"/>
<xsl:template match="/">
    <html>
        <head>
            <title/>
        </head>
        <body>
            <xsl:apply-templates/>
            <ol>
                <xsl:call-template name="grouping">
                    <xsl:with-param name="par" select="w:document/w:body/w:p[1]"/>
                </xsl:call-template>
            </ol>
        </body>
    </html>
</xsl:template>
<xsl:template name="grouping">
    <xsl:param name="par"/>
    <xsl:choose>
        <xsl:when test="$par/w:pPr/w:numPr/w:ilvl/@w:val >0">
            <xsl:variable name="level" select="$par/w:pPr/w:numPr/w:ilvl/@w:val"/>
            <li>
                <xsl:value-of select="$par/w:r/w:t"/>
            </li>
            <xsl:call-template name="order">
                <xsl:with-param name="par" select="$par/following-sibling::w:p[1]"/>
                <xsl:with-param name="levelPrevious" select="$level"/>
            </xsl:call-template>
            <xsl:call-template name="grouping">
                <xsl:with-param name="par" select="$par/following-sibling::w:p[2]"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:if test="$par/following-sibling::w:p[1]">
                <xsl:call-template name="grouping">
                    <xsl:with-param name="par" select="$par/following-sibling::w:p[1]"/>
                </xsl:call-template>
            </xsl:if>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
<xsl:template name="order">
    <xsl:param name="par"/>
    <xsl:param name="levelPrevious"/>
    <xsl:choose>
        <xsl:when test="$par/w:pPr/w:numPr/w:ilvl/@w:val > $levelPrevious">
            <ol>
                <li>
                    <xsl:value-of select="$par/w:r/w:t"/>
                </li>
                <xsl:call-template name="grouping">
                    <xsl:with-param name="par" select="$par/following-sibling::w:p[1]"/>
                </xsl:call-template>
            </ol>
        </xsl:when>
        <xsl:otherwise>
                <li>
                    <xsl:value-of select="$par/w:r/w:t"/>
                </li>
        </xsl:otherwise>
        </xsl:choose>
</xsl:template>

And the Result is :

1.First Item
2.Second Item
3.Third Item
   1.Third Item – One
   2.Third Item – Two
       1.Sample Item A
       2.Sample Item B
       3.Fo u rth Item
   3.Sample Item B
   4.Fo u rth Item
4.Third Item – Two
   1.Sample Item A
   2.Sample Item B
   3.Fo u rth Item
5.Sample Item B
6.Fo u rth Item

Expected Result is :

1.First Item
2.Second Item
3.Third Item
       a.Third Item – One
       b.Third Item – Two
          I.Sample Item A
          II.Sample Item B
4.Fourth Item

The thing is that i dont know how to add the 4.item into first group and the third item also iterating itself in other level.How can i fix this problem any idea?

*Edit:I am almost there just need to get rid of this copied elements after the fourth item!

1
Please show source XML and full XSLT for reproducibility on our end.Parfait
It is almost impossible to put it here the entire code..What i am trying to understand is how the recursive functions work.In this case i am doing something very stupid and cant see what it is.I dont know if i can upload the files some other websites and share here.Sojimanatsu
Usually XSLT scripts are not that long and we only need a sample source XML. You can try pastebin or GitHub gists to dump code/data.Parfait
Okay i edited the XSLT and added the sample XML file from DOCX.Sojimanatsu
I attempted a solution but what really is tough is determining the nested list items as their original structure are all same-level <w:p> tags. Here, in this pseudo data file, it says First Item, Second Item, ... but no where is there an indicator for Third Item - One or Sample Item to be nested. How to determine nested items?Parfait

1 Answers

1
votes

Consider this XSLT 1.0 solution using a recursive template. Do note your XML input was not fully complete as the very important top tags and namespace URI were not included. Below XSLT assumes the following XML structure. If actual XML is still different, of course change the correspoinding XSLT references accordingly.

XML

<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
    <w:body>
    <!-- repeat <w:p> tags -->
    </w:body>
</w:document>

XSL

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                              xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
                              exclude-result-prefixes="w">
 <xsl:output method="html" doctype-system="about:legacy-compat" indent="yes"/> 
 <xsl:strip-space elements="*"/>

   <xsl:template match="/w:document/w:body">
      <html>
          <head>
              <title/>
          </head>
          <body>
            <ol>
               <xsl:apply-templates select="w:p[w:pPr/w:numPr/w:ilvl/@w:val='1']"/>
            </ol>
          </body>
     </html>
   </xsl:template>

   <xsl:template match="w:p">
      <li><xsl:apply-templates select="w:r"/></li>                
      <xsl:call-template name="nest">
         <xsl:with-param name="type" select="'a'"/>
         <xsl:with-param name="par" select="2"/>
         <xsl:with-param name="val" select="following-sibling::*"/>             
      </xsl:call-template>
   </xsl:template>

   <xsl:template name="nest">
      <xsl:param name="type"/>
      <xsl:param name="par"/>
      <xsl:param name="val"/>

      <xsl:if test="$val[1]/w:pPr/w:numPr/w:ilvl/@w:val=$par">
         <ol type="{$type}">
            <xsl:for-each select="$val">
               <xsl:if test="w:pPr/w:numPr/w:ilvl/@w:val=$par">
                  <li><xsl:apply-templates select="w:r"/></li>                  
                  <xsl:call-template name="nest">
                     <xsl:with-param name="type" select="'I'"/>
                     <xsl:with-param name="par" select="$par+1"/>
                     <xsl:with-param name="val" select="following-sibling::*"/>
                  </xsl:call-template>
               </xsl:if>
            </xsl:for-each>
         </ol>
      </xsl:if>
   </xsl:template>

</xsl:stylesheet>

HTML Output

<!DOCTYPE html SYSTEM "about:legacy-compat">
<html>
  <head>
    <META http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title></title>
  </head>
  <body>
    <ol>
      <li>First Item</li>
      <li>Second Item</li>
      <li>Third Item</li>
      <ol type="a">
        <li>Third Item - One</li>
        <li>Third Item - Two</li>
        <ol type="I">
          <li>Sample Item A</li>
          <li>Sample Item A</li>
        </ol>
      </ol>
      <li>Fourth Item</li>
    </ol>
  </body>
</html>

HTML Output