Welcome to OpenXML Developer Sign in | Join | Help

Converting WordML Lists to XML/HTML using XSLT

Last post 10-17-2008, 2:11 PM by k5tm. 11 replies.
Sort Posts: Previous Next
  •  05-12-2008, 2:10 PM 3177

    Converting WordML Lists to XML/HTML using XSLT

    I am making a template to translate WordProcessingML to the XML used by my company. It is 99% HTML, but uses some unique tags. The problem I am having is with the list items. WordML identifies each list with a w:ilfo/@w:val nested in the w:p/w:pPr tags to identify which list a w:p item belongs to. The problem is getting the appropriate <ul> or <ol> around the appropriate <li> tags. I am not having any problems choosing between ol or ul, but rather putting the tags around ALL of the li tags appropriately. In my code (see below) I match w:p with a w:ilfo/@w:val != the preceding-sibling::w:p/descendant::w:ilfo/@w:val, then with a for-each select ".." grab all of the following sibling w:p tags with a descendant w:ilfo/@w:val equal to the current w:p tag. I have a template that matches the tags and creates <li> tags around them. I also have a template that creates new ol/ul tags that have teh same w:ilfo/@w:val but have a greater w:ilvl (indent level) than the preceding-sibling's w:ilvl. This works recursively (so each time it has a greater indent, call/match the template again and make the appropriate ul/ol tag.

    The problem with the template is that it does not transform the w:p tags in between the <li> tags (ex. one big ordered list with several paragraphs in between each w:p/w:ilfo) or the other tags between (ex. table tags, link tags, img tags, etc.). I do not have any more ideas on how to transform the lists (Ideally, I'd grab all tags before the last w:ilfo value and apply their templates). Here is the code transforming the lists:


    <xsl:template match='w:p[w:pPr/w:listPr/w:ilfo/@w:val > 0 and not(w:p[w:pPr/w:listPr/w:ilfo/@w:val = preceding-sibling::w:p/descendant::w:ilfo/@w:val])]' priority="2" name="isListP">
        <!-- Declare some variables used throughout this template -->
        <xsl:variable name="listID"><xsl:value-of select="descendant::w:ilfo/@w:val"/></xsl:variable>
        <xsl:variable name="listType">
            <xsl:choose>
                <xsl:when test='descendant::wx:t/@wx:val = "·" or descendant::wx:t/@wx:val="o" or descendant::wx:t/@wx:val="§"'>ul</xsl:when>
                <xsl:otherwise>ol</xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:variable name="indentLevel"><xsl:value-of select="descendant::w:ilvl/@w:val"/></xsl:variable>
       
        <xsl:choose>
        <xsl:when test='not(preceding-sibling::w:p[descendant::w:ilfo/@w:val >= $listID])'>
            <xsl:element name="{$listType}">
                <xsl:for-each select='following::w:p[descendant::w:ilfo/@w:val = $listID and descendant::w:ilvl/@w:val >= $indentLevel]'>
                    <xsl:choose>
                    <xsl:when test='descendant::w:ilvl/@w:val = $indentLevel+1 and not(descendant::w:ilvl/@w:val = preceding-sibling::w:p/descendant::w:ilvl/@w:val)'>
                        <xsl:call-template name='restOfList' />
                    </xsl:when>
                    <xsl:when test='descendant::w:ilvl/@w:val > $indentLevel+1'>
                    </xsl:when>
                    <xsl:otherwise><xsl:call-template name="listItems" /></xsl:otherwise></xsl:choose>
                </xsl:for-each>
            </xsl:element>
        </xsl:when>
        </xsl:choose>
    </xsl:template>

    <!-- Template to handle list indents recursively -->
    <xsl:template name="restOfList">
        <xsl:variable name="listID"><xsl:value-of select="descendant::w:ilfo/@w:val"/></xsl:variable>
        <xsl:variable name="listType">
            <xsl:choose>
                <xsl:when test='descendant::wx:t/@wx:val = "·" or descendant::wx:t/@wx:val="o" or descendant::wx:t/@wx:val="§"'>ul</xsl:when>
                <xsl:otherwise>ol</xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:variable name="indentLevel"><xsl:value-of select="descendant::w:ilvl/@w:val"/></xsl:variable>
       
        <xsl:element name="{$listType}">
                <xsl:for-each select='following::w:p[descendant::w:ilfo/@w:val = $listID and descendant::w:ilvl/@w:val >= $indentLevel]'>
                    <xsl:choose>
                    <xsl:when test='descendant::w:ilvl/@w:val = $indentLevel+1 and not(descendant::w:ilvl/@w:val = preceding-sibling::w:p/descendant::w:ilvl/@w:val)'>
                        <xsl:call-template name='restOfList' />
                    </xsl:when>
                    <xsl:when test='descendant::w:ilvl/@w:val > $indentLevel+1'>
                    </xsl:when>
                    <xsl:otherwise><xsl:call-template name="listItems" /></xsl:otherwise></xsl:choose>
                </xsl:for-each>
        </xsl:element>
    </xsl:template>

    <!-- List Items Template -->
    <xsl:template name="listItems">
        <li><xsl:call-template name="isParProperty" /></li>
    </xsl:template>


    Anything would be a help at this point, seeing how the only other option I have at this time is to transform the w:p tags that have descendant::w:ilfo into <li> tags and manually add in the list tags. This is a painful process seeing how the majority of the documents being transformed are 300+ pages, containing many lists with different indentations...
  •  05-12-2008, 5:49 PM 3178 in reply to 3177

    Re: Converting WordML Lists to XML/HTML using XSLT

    A quick update- I did manage to come up with an idea of how to solve my problem, but I am having a hard time selecting the correct XPath's for some items (cannot figure out where though). I use generate-id() on the last items of the list, and select everything before that in the for-loop. I also generate an id in another template for the last item with a specified indent. The XPath problems are that I want to start a listItem when the Template comes across the first w:p/descendant::w:ilfo/@w:val (ie. first appearance of the w:val) and the first time a w:p/descendant::w:ilvl/@w:val < the current node's. here is the code:

    <xsl:template match='w:p[w:pPr/w:listPr/w:ilfo/@w:val > 0 and not(w:p[descendant::w:ilfo/@w:val = preceding::w:p/descendant::w:ilfo/@w:val])]' priority="3" name="isListP">
        <!-- Declare some variables used throughout this template -->
        <xsl:variable name="listID"><xsl:value-of select="descendant::w:ilfo/@w:val"/></xsl:variable>
        <xsl:variable name="listType">
            <xsl:choose>
                <xsl:when test='descendant::wx:t/@wx:val = "·" or descendant::wx:t/@wx:val="o" or descendant::wx:t/@wx:val="§"'>ul</xsl:when>
                <xsl:otherwise>ol</xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:variable name="indentLevel"><xsl:value-of select="descendant::w:ilvl/@w:val"/></xsl:variable>
        <xsl:variable name="lastItem" select="generate-id(following::w:p[descendant::w:ilfo/@w:val = $listID][last()])" />
       
       
        <xsl:element name="{$listType}">
            <xsl:call-template name="listItems" />
           
            <xsl:for-each select="following::*[following::w:p[generate-id() = $lastItem]]">       
                <xsl:choose>
                <xsl:when test="descendant::w:ilvl/@w:val = $indentLevel"><xsl:call-template name="listItems" /></xsl:when>
                <xsl:when test="descendant::w:ilvl/@w:val = preceding-sibling::w:p[1]/descendant::w:ilvl/@w:val + 1"><xsl:call-template name="isListIndent" /></xsl:when>
                <xsl:otherwise></xsl:otherwise></xsl:choose>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>

    <xsl:template match='w:p[w:pPr/w:listPr/w:ilfo/@w:val > 0 and w:p[w:pPr/w:listPr/w:ilfo/@w:val = preceding-sibling::w:p/descendant::w:ilfo/@w:val] and descendant::w:ilvl/@w:val > preceding-sibling::w:p[1]/descendant::w:ilvl/@w:val]' name='isListIndent' priority="2">
        <!-- Declare some variables used throughout this template -->
        <xsl:variable name="listID"><xsl:value-of select="descendant::w:ilfo/@w:val"/></xsl:variable>
        <xsl:variable name="listType">
            <xsl:choose>
                <xsl:when test='descendant::wx:t/@wx:val = "·" or descendant::wx:t/@wx:val="o" or descendant::wx:t/@wx:val="§"'>ul</xsl:when>
                <xsl:otherwise>ol</xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:variable name="indentLevel"><xsl:value-of select="descendant::w:ilvl/@w:val"/></xsl:variable>
        <xsl:variable name="lastIndList" select="generate-id(following::w:p[descendant::w:ilvl/@w:val &lt; $indentLevel][1])" />
       
       
        <xsl:element name="{$listType}">
           
            <xsl:call-template name="listItems" />
            <xsl:for-each select="following::*[following::w:p[generate-id() = $lastIndList]]">
                <xsl:choose>
                <xsl:when test="descendant::w:ilvl/@w:val = $indentLevel"><xsl:call-template name="listItems" /></xsl:when>
                <xsl:when test="descendant::w:ilvl/@w:val = preceding-sibling::w:p/descendant::w:ilvl/@w:val+1"><xsl:call-template name="isListIndent" /></xsl:when>
                <xsl:otherwise></xsl:otherwise></xsl:choose>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>

    <xsl:template name="listItems" >
        <li><xsl:call-template name="isParProperty" /></li>
    </xsl:template>


  •  08-30-2008, 12:24 PM 3621 in reply to 3178

    Re: Converting WordML Lists to XML/HTML using XSLT

    Hi,

    I am working on a similar thing and am stuck with generating HTML tags for lists in the docx file. Seems like you have figured out a way to a greater extent. Could you please let me know whether you have sorted it out by now?

    If so,  can you please share it? It would be a great help for me. Another thing, are you working on word 2007 files? Because the docx files have somewhat different set of tags than what you have above.

     

    /Suralk

  •  09-02-2008, 2:36 PM 3637 in reply to 3621

    Re: Converting WordML Lists to XML/HTML using XSLT

    Unfortunately, the only other way I could come up with was creating <li> objects with attributes to include listId, listType, and indent level. Then, use a java app to parse the xml document and create the 'listType' Elements as each unique listId is reached. Then, loop through and look for changes in indent level, removing the node with a higher level, creating the listType element and placing it in the previous list item. I have not completed the code for all of this yet, but I will be happy to share once completed... I do not work with .docx files yet, but I'm sure they will be ugly/poor xml just like word 2003.
  •  09-03-2008, 12:10 PM 3643 in reply to 3637

    Re: Converting WordML Lists to XML/HTML using XSLT

    Hi,

    thanks for sharing your views. I also managed to implement this to a greater extent. Everything works fine but one problem remains. Suppose we are having a list in word like this:

    1. aa

    2. bb

        2.1 cc

        2.2  dd

            2.2.1 111

            2.2.2  22222

    3. ee

       3.3 ff

       3.4 gg

    My code would generate somethin like this:

    •  aa
    • bb
      • cc
      • dd
        •  111
        •  2222
      • ff
      • gg
    •  ee
      •  ff
      •  gg

    as you can see, the sublist under the 'ee' has got itself appended to the 'bb' also :(

    I am also using a for-loop to go through the sibling nodes, but for each of these nodes, I want to get the first preceding sibling of that node, which has a 'ilvl' less than this sibling node. I want to get this node, so that I can compare it with the calling node. I am trying to use generate-id function here.

    In words, it is something like this: At each sibling node, get the node id of its first preceding sibling, which has a ilvl value one less than this current sibling node.

    What I had in mind is something like this, but it does not work L

    <xsl:variable name="lastIndList" select="generate-id(preceding-sibling::w:p[preceding-sibling::w:p/w:ilvl/@w:val &lt; descendant::w:ilvl/@w:val][1])" />

    For example, if 'bb' is the calling node for the sublist, I want to make sure that the preceding sibling of 'ff' is not coming under  'bb', so it would not append itself to 'bb'.

    I know this is pure XSLT issue, but since I'm a newbie to XSLT, I have been struggling with this for days. Hope you can help me to figure this out.

    thanks in advance,

    /Suralk

    ps- yeah, u r right. word 2007 has much worse xml than 2003 I think. In 2003, youh ave everything you need in one XML file I think, but for 2007, you have to access a whole lot of other XML's also. As for the lists, the style information is stored ina separate numbering.xml, so you have to read that also :(

     

  •  09-09-2008, 3:39 PM 3670 in reply to 3643

    Re: Converting WordML Lists to XML/HTML using XSLT

    /Suralk

    Can you post your XSLT?  At least the portion dealing with the list?  I am just starting to work on this transformation, I am very familiar with XSLT, and probably could help you diagnose your problem.  In general it would seem your approach would work, so there is probably some minor thing that needs to be fixed.

    (BTW, for an XSLT 'newbie' you are in some very interesting areas of XSLT!)

    Tom
  •  09-12-2008, 2:38 AM 3684 in reply to 3670

    Re: Converting WordML Lists to XML/HTML using XSLT

    It is a modification of the above XSLT template, but in Word2007. The condtion marked in bold italic large text should be changedto make sure that we compare our calling node with the first immediate sibling who has a less value for NumID when compared with the current node in that for-loop

    <xsl:template name="isListP" >

    <xsl:if test="((w:pPr/w:numPr/w:numId/@w:val > 0) and not(descendant::w:numId/@w:val = preceding::w:p/descendant::w:numId/@w:val))">

    <xsl:variable name="listID">

    <xsl:value-of select="descendant::w:numId/@w:val"/>

    </xsl:variable>

    <xsl:variable name="indentLevel">

    <xsl:value-of select="descendant::w:ilvl/@w:val"/>

    </xsl:variable>

    <xsl:variable name="NumberingId">

    <xsl:value-of select="ancestor::w:document/Numbering/numId[attribute::id=$listID]/@id"/>

    </xsl:variable>

    <xsl:variable name="listType">

    <xsl:value-of select="ancestor::w:document/Numbering/numId/Level[(@levelId=$indentLevel)][$listID=$NumberingId]"/>

    </xsl:variable>

    <xsl:element name="{$listType}">

    <xsl:call-template name="listItems" />

    <xsl:for-each select="following-sibling::w:p">

    <xsl:choose>

    <xsl:when test="((descendant::w:ilvl/@w:val = $indentLevel) and descendant::w:numId/@w:val = $listID)">

    <xsl:call-template name="listItems" />

    </xsl:when>

    <!--xsl:when test="((descendant::w:ilvl/@w:val = (preceding-sibling::w:p[1]/descendant::w:ilvl/@w:val)+1) and (descendant::w:numId/@w:val = $listID)) "-->

    <xsl:when test="((descendant::w:ilvl/@w:val = $indentLevel+1) and (descendant::w:numId/@w:val = $listID)) ">

    <xsl:call-template name="isListIndent" >

    <xsl:with-param name="parent" select="generate-id()" />

    </xsl:call-template>

    </xsl:when>

    <xsl:otherwise></xsl:otherwise>

    </xsl:choose>

    </xsl:for-each>

    </xsl:element>

    </xsl:if>

    </xsl:template>

    <!--xsl:template match='w:p[w:pPr/w:numPr/w:numId/@w:val > 0 and w:p[w:pPr/w:numPr/w:numId/@w:val = preceding-sibling::w:p/descendant::w:numId/@w:val] and descendant::w:ilvl/@w:val > preceding-sibling::w:p[1]/descendant::w:ilvl/@w:val]' name='isListIndent' priority="2"-->

    <xsl:template name='isListIndent'>

    <xsl:param name="parent" />

    <!-- Declare some variables used throughout this template -->

    <xsl:if test='((w:pPr/w:numPr/w:numId/@w:val > 0) and (w:pPr/w:numPr/w:numId/@w:val = preceding-sibling::w:p/descendant::w:numId/@w:val) and (descendant::w:ilvl/@w:val > preceding-sibling::w:p[1]/descendant::w:ilvl/@w:val))'>

    <xsl:variable name="listID">

    <xsl:value-of select="descendant::w:numId/@w:val"/>

    </xsl:variable>

    <xsl:variable name="indentLevel">

    <xsl:value-of select="descendant::w:ilvl/@w:val"/>

    </xsl:variable>

    <xsl:variable name="NumberingId">

    <xsl:value-of select="ancestor::w:document/Numbering/numId[attribute::id=$listID]/@id"/>

    </xsl:variable>

    <xsl:variable name="listType">

    <xsl:value-of select="ancestor::w:document/Numbering/numId/Level[(@levelId=$indentLevel)][$listID=$NumberingId]"/>

    </xsl:variable>

    <xsl:variable name="lastIndList" select="generate-id(preceding-sibling::w:p[preceding-sibling::w:p/w:ilvl/@w:val &lt; descendant::w:ilvl/@w:val][1])" />

    <xsl:element name="{$listType}">

    <xsl:call-template name="listItems" />

    <xsl:for-each select="following::w:p">

    <xsl:choose>

    <xsl:when test="((descendant::w:ilvl/@w:val = $indentLevel) and descendant::w:numId/@w:val = $listID)">

    <xsl:call-template name="listItems" />

    <xsl:value-of select="$lastIndList"/>

    <xsl:value-of select="$parent"/>

    </xsl:when>

    <xsl:when test="((descendant::w:ilvl/@w:val = $indentLevel + 1) and (descendant::w:numId/@w:val = $listID)) ">

    <xsl:call-template name="isListIndent" >

    <xsl:with-param name="parent" select="generate-id()" />

    </xsl:call-template>

    </xsl:when>

    <xsl:otherwise></xsl:otherwise>

    </xsl:choose>

    </xsl:for-each>

    </xsl:element>

    </xsl:if>

    </xsl:template>

  •  09-23-2008, 10:37 AM 3731 in reply to 3684

    Re: Converting WordML Lists to XML/HTML using XSLT

    suralk,

    I apologize for not replying sooner.  I have been diverted from the task that led me to your post.  However, I am now back on that task, so I will have an opportunity (I hope) to study your solution by the end of the week.
  •  09-23-2008, 11:17 AM 3733 in reply to 3731

    Re: Converting WordML Lists to XML/HTML using XSLT

    hi, thanks. I tried everyway I knew and finally gave up. Now I am stuck with a VML conversion.
    Hope you would find a way out.

    thanks again

    /suralk
  •  10-06-2008, 6:10 PM 3758 in reply to 3733

    Re: Converting WordML Lists to XML/HTML using XSLT

    suralk:
    Hope you would find a way out.


    Yes, I did.  Some research on this problem turned up a nice tail recursion solution attributed to Michael Kay. 

    I created a template that allows me to characterize a paragraph's styling in a string.  For my purposes a change in adjacent paragraphs' characterization flagged the end of a group of paragraphs.  This simplification allowed me to use a simple equality test.  For more complicated tests of 'groupness' between adjacent paragraphs, one could create a template that does the comparison of two paragraphs' styles and returns a boolean; this is left as an exercise.

        <xsl:template match="w:sdtContent" mode="withStyling">
            <xsl:apply-templates select="./w:p | .//w:tbl" mode="withStyling">
            </xsl:apply-templates>
        </xsl:template>

        <xsl:template match="w:p" mode="withStyling">
            <xsl:variable name="thisParaStyle"><xsl:apply-templates select="self::w:p" mode="characterizeParagraph"/></xsl:variable>
            <xsl:variable name="prevParaStyle">
                <xsl:choose>
                <xsl:when test="preceding-sibling::*[1][self::w:p]"><xsl:apply-templates select="preceding-sibling::*[1][self::w:p]" mode="characterizeParagraph"/></xsl:when>
                <xsl:otherwise/>
                </xsl:choose>
            </xsl:variable>
            <xsl:choose>
                <xsl:when test="$thisParaStyle = $prevParaStyle"/><!-- this paragraph has already been done through recursion -->
                <xsl:otherwise><!-- this is the first of a group of siblings -->
                    <xsl:choose>
                    <xsl:when test="contains($thisParaStyle,'ListParagraph') and contains($thisParaStyle,'bullet')">
                        <ul>
                            <xsl:apply-templates select="." mode="siblingListItems">
                                <xsl:with-param name="thisParaStyle" select="$thisParaStyle"/>
                            </xsl:apply-templates>   
                        </ul>
                    </xsl:when>
                    <xsl:when test="contains($thisParaStyle,'ListParagraph')">
                        <ol>
                            <xsl:apply-templates select="." mode="siblingListItems">
                                <xsl:with-param name="thisParaStyle" select="$thisParaStyle"/>
                            </xsl:apply-templates>   
                        </ol>
                    </xsl:when>
                    <xsl:otherwise>
                        <p>
                            <xsl:apply-templates select=".//w:t | .//w:br" mode="withStyling"/>
                        </p>
                    </xsl:otherwise>
                    </xsl:choose>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>

        <xsl:template match="w:p" mode="siblingListItems">
            <xsl:param name="thisParaStyle"/>
            <xsl:variable name="nextParaStyle">
                <xsl:choose>
                <xsl:when test="following-sibling::*[1][self::w:p]"><xsl:apply-templates select="following-sibling::*[1][self::w:p]" mode="characterizeParagraph"/></xsl:when>
                <xsl:otherwise/>
                </xsl:choose>
            </xsl:variable>
            <li><xsl:apply-templates select=".//w:t | .//w:br" mode="withStyling"/></li>
            <xsl:if test="$thisParaStyle = $nextParaStyle">
                <xsl:apply-templates select="following-sibling::*[1][self::w:p]"  mode="siblingListItems">
                    <xsl:with-param name="thisParaStyle" select="$nextParaStyle"/>
                </xsl:apply-templates>
            </xsl:if>
        </xsl:template>

        <xsl:template match="w:t" mode="withStyling">
        <!--  process your text element here -->
        </xsl:template>

        <xsl:template match="w:p" mode="characterizeParagraph">
            <xsl:variable name="styleName" select="./w:pPr/w:pStyle/@w:val"/>
            <xsl:variable name="theLevel" select="./w:pPr/w:numPr/w:ilvl/@w:val"/>
            <xsl:variable name="theNumId" select="./w:pPr/w:numPr/w:numId/@w:val"/>
            <xsl:variable name="abstractNumber" select="/pkg:package/pkg:part[@pkg:name='/word/numbering.xml']/pkg:xmlData/w:numbering/w:num[@w:numId=$theNumId]/w:abstractNumId/@w:val"/>
            <xsl:variable name="indentType" select="/pkg:package/pkg:part[@pkg:name='/word/numbering.xml']/pkg:xmlData/w:numbering/w:abstractNum[@w:abstractNumId=$abstractNumber]/w:lvl[@w:ilvl=$theLevel]/w:numFmt/@w:val"/>
            <xsl:value-of select="concat('st=',$styleName,';lvl=',$theLevel,';type=',$indentType,';')"/>
        </xsl:template>
           
        <xsl:template match="w:br" mode="withStyling"><p/></xsl:template>

  •  10-07-2008, 11:34 AM 3768 in reply to 3758

    Re: Converting WordML Lists to XML/HTML using XSLT

    Some further explanation about the following construct:
    <xsl:when test="preceding-sibling::*[1][self::w:p]">
    This XPath expression can be read as:
    Is the first preceding-sibling element a w:p element?
    Contrast this to preceding-sibling::w:p[1] which returns the first w:p element on the preceding-sibling axis.
  •  10-17-2008, 2:11 PM 3807 in reply to 3758

    Re: Converting WordML Lists to XML/HTML using XSLT

    I found some mistakes in the previous template in the case where no bullet or numbered lists were present.  So, these two templates contain the corrections.

    <xsl:template match="w:p" mode="withStyling">
      <xsl:variable name="thisParaStyle"><xsl:apply-templates select="self::w:p" mode="characterizeParagraph"/></xsl:variable>
      <xsl:variable name="prevParaStyle">
          <xsl:choose>
          <xsl:when test="preceding-sibling::*[1][self::w:p]"><xsl:apply-templates select="preceding-sibling::*[1][self::w:p]" mode="characterizeParagraph"/></xsl:when>
          <xsl:otherwise/>
          </xsl:choose>
      </xsl:variable>
      <xsl:choose>
        <xsl:when test="$thisParaStyle = $prevParaStyle"/>
        <xsl:otherwise><!-- this is the first of a group of siblings -->
          <xsl:choose>
          <xsl:when test="contains($thisParaStyle,'ListParagraph') and contains($thisParaStyle,'bullet')">
            <ul>
              <xsl:apply-templates select="." mode="siblingListItems">
                <xsl:with-param name="thisParaStyle" select="$thisParaStyle"/>
                <xsl:with-param name="elementName">li</xsl:with-param>
              </xsl:apply-templates>   
            </ul>
          </xsl:when>
          <xsl:when test="contains($thisParaStyle,'ListParagraph')">
            <ol>
              <xsl:apply-templates select="." mode="siblingListItems">
                <xsl:with-param name="thisParaStyle" select="$thisParaStyle"/>
                <xsl:with-param name="elementName">li</xsl:with-param>
              </xsl:apply-templates>   
            </ol>
          </xsl:when>
          <xsl:otherwise>
              <xsl:apply-templates select="." mode="siblingListItems">
                <xsl:with-param name="thisParaStyle" select="$thisParaStyle"/>
                <xsl:with-param name="elementName">p</xsl:with-param>
              </xsl:apply-templates>   
          </xsl:otherwise>
          </xsl:choose>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>

    <xsl:template match="w:p" mode="siblingListItems">
      <xsl:param name="thisParaStyle"/>
      <xsl:param name="elementName"/>
      <xsl:variable name="nextParaStyle">
          <xsl:choose>
        <xsl:when test="following-sibling::*[1][self::w:p]"><xsl:apply-templates select="following-sibling::*[1][self::w:p]" mode="characterizeParagraph"/></xsl:when>
        <xsl:otherwise/>
        </xsl:choose>
      </xsl:variable>
      <xsl:element name="{$elementName}"><xsl:apply-templates select=".//w:t | .//w:br | .//w:drawing" mode="withStyling"/></xsl:element>
      <xsl:if test="$thisParaStyle = $nextParaStyle">
          <xsl:apply-templates select="following-sibling::*[1][self::w:p]"  mode="siblingListItems">
          <xsl:with-param name="thisParaStyle" select="$nextParaStyle"/>
          <xsl:with-param name="elementName" select="$elementName"/>
        </xsl:apply-templates>
      </xsl:if>
    </xsl:template>

View as RSS news feed in XML