wordpress hit counter
View revisions to a WordprocessingML document in a browser - OpenXML Developer - Blog - OpenXML Developer

View revisions to a WordprocessingML document in a browser

Blog

Samples, Demos, and Reference Articles

View revisions to a WordprocessingML document in a browser

  • Comments 1

Article by: MuthuKumar Arjunan of SONATA SOFTWARE LIMITED

 

This article explains how any WordprocessingML document whose changes are tracked can be viewed in a browser.

 

It explains the usage of ASP.NET application in converting a WordprocessingML document with simple textual content and comments into HTML using XSLT. If the document revision (“track changes”) is set “on”, then the tracked changes are also converted to HTML.

 

This ASP.NET application enables the user to upload the WordprocessingML document, which is unzipped into a set of Open XML parts (files) using SharpZipLib.  The document is then converted into HTML.

 

The sample document (SampleDoc.docx) in this example has its “track changes” flag set on. The XSLT, the source code for ASP.NET application (called “AsynchronousProcessing”) and the WordprocessingML document (“sampleDoc.docx”) are available for download.

 

The XSLT used for conversion is:

 

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/3/main">

      <xsl:output method="html"/>

      <xsl:param name="blnPublish">false</xsl:param>

  <xsl:preserve-space elements="w:t"/>

      <xsl:template match="/">

            <xsl:apply-templates select="//w:body"/>

      </xsl:template>

      <xsl:template match="w:body">

            <html>

                  <head>

                        <script language="JScript">

                   function changeDisplayState (anchorid,divid,datatype)

                   {

               

                        d=document.getElementById(anchorid);

                        e=document.getElementById(divid);

                        if (e.style.display == 'none' || e.style.display =="")

                        {

                              e.style.display = 'block';

                              d.innerHTML = '<u style="color: Fuchsia; background-color: grey; font-size:8pt;">hide tbl</u>';

                        }

                        else

                        {

                              e.style.display = 'none';

                              if (datatype=='comdata')

                              {

                              d.innerHTML = '<sup style="color: green; background-color: grey; font-size:8pt;">c*</sup>';

                              }

                              else

                              {

                              d.innerHTML = '<sub style="color: green; background-color: grey; font-size:8pt;">?*</sub>';

                              }

                        }

                  }

                  </script>

                  </head>

                  <body>

                 

                       

                              <xsl:apply-templates/>

                       

                  </body>

            </html>

      </xsl:template>

  <!--Template to process the "Paragraph : w:p" node-->

      <xsl:template match="w:p">

            <div>

                  <!--<xsl:apply-templates select="w:r"/>

      --><!--if NOT in Publish mode,then process the "deleted" tag--><!--

                  <xsl:if test="not($blnPublish='true')">

                        <xsl:apply-templates select="w:del"/>

                  </xsl:if >

            <xsl:apply-templates select="w:ins"/>-->

      <!--<xsl:choose>

        <xsl:when test="w:r//w:t[@xml:space='preserve']">

          <pre>

          <xsl:apply-templates select="node()"/>

          </pre>

        </xsl:when>

        <xsl:otherwise>

          <xsl:apply-templates select="node()"/>

        </xsl:otherwise>

      </xsl:choose>-->

 

      <xsl:apply-templates select="node()"/>

    

            </div>

      </xsl:template>

  <!--Template to process the "Run : w:r" node-->

      <xsl:template match="w:r">

    <xsl:apply-templates select="w:t"/>

  </xsl:template>

  <!--Template to process the "Text : w:t" node-->

  <xsl:template match="w:t">

   <span>

      <xsl:apply-templates select="../w:rPr"/>

     <!--<xsl:value-of select="." />-->

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

       <xsl:with-param name="inString" select="."/>

     </xsl:call-template>

 

 

   </span>

      </xsl:template>

  <xsl:template name="replaceSpace">

    <xsl:param name="inString"/>

    <xsl:choose>

      <xsl:when test="contains($inString, ' ')">

        <xsl:value-of select="substring-before($inString, ' ')"/>

        <xsl:value-of select="_nbsp"/>;

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

          <xsl:with-param name="inString" select="substring-after($inString, ' ')"/>

        </xsl:call-template>

      </xsl:when>

      <xsl:otherwise>

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

      </xsl:otherwise>

    </xsl:choose>

  </xsl:template>

  <!--Template to process the "rowProperty : w:rPr" node-->

      <xsl:template match="w:rPr">

            <xsl:attribute name="style"><xsl:apply-templates/></xsl:attribute>

      </xsl:template>

      <xsl:template match="w:u">text-decoration:underline;</xsl:template>

      <xsl:template match="w:b">font-weight:bold;</xsl:template>

      <xsl:template match="w:i">font-style:italic;</xsl:template>

      <xsl:template match="w:color">

            color:<xsl:value-of select="@w:val"/>;

      </xsl:template>

      <xsl:template match="w:highlight">

            background:<xsl:value-of select="@w:val"/>;

      </xsl:template>

      <xsl:template match="w:rFonts">

            font-family:<xsl:value-of select="@w:ascii"/>;

      </xsl:template>

 

  <!--Template to process the "deleted-  w:del" Node-->

  <xsl:template match="w:del">

    <!--Strike the deleted text-->

    <xsl:if test="not($blnPublish='true')">

    <strike>

      <xsl:value-of select="w:r/w:delText" disable-output-escaping="yes"/>

    </strike>

    <!--Generate a unique id for deletion details : the links and div(holding table containing deletion details)-->

    <xsl:variable name="delUniqId" select="generate-id(.)"/>

    <span title=" by {@w:author} " style="color: #9F141A; background-color: yellow; font-size:8pt;">

 

      <a id="{$delUniqId}x" href="BLOCKED SCRIPTchangeDisplayState('{$delUniqId}x','{$delUniqId}','deldata')">

        <sub style="color: green; background-color: grey; font-size:10pt;">?*</sub>

      </a>

 

    </span>

    <div id="{$delUniqId}" style="display:none">

      <table border="1" style="color: green; background-color: yellow; font-size:10pt;">

        <tr>

          <td>

            <b> author:</b>

          </td>

          <td>

            <xsl:value-of select="@w:author"/>;

          </td>

        </tr>

        <tr>

          <td>

            <b> DateTime:</b>

          </td>

          <td>

            <xsl:value-of select="@w:date"/>;

          </td>

        </tr>

      </table>

    </div>

    <xsl:apply-templates select="w:commentRangeStart"/>

      </xsl:if>

  </xsl:template>

  <!--Template to process the "inserted-  w:ins" Node-->

  <xsl:template match="w:ins">

    <!--if NOT in Publish mode,then underline the "inserted" text-->

    <xsl:if test="not($blnPublish='true')">

      <u style="color:red;">

        <xsl:apply-templates select="w:r"/>

      </u>

      <xsl:apply-templates select="w:commentRangeStart"/>

    </xsl:if>

    <!--if it is in  Publish mode,then DONOT underline the "inserted" text-->

    <xsl:if test="$blnPublish='true'">

      <xsl:apply-templates select="w:r"/>

    </xsl:if>

 

  </xsl:template>

  <!--Template to process the "CommentRange-  w:commentRangeStart" Node-->

      <xsl:template match="w:commentRangeStart">

      <xsl:if test="not($blnPublish='true')">

            <xsl:variable name="CommentId" select="@w:id"/>

    <!--Generate a unique id for Comment details : the links and div(holding table containing Comment details)-->

            <xsl:variable name="CommentUniqId" select="generate-id(.)"/>

   

            <span title="{//w:comment[@w:id = $CommentId]} " style="color: #9F141A; background-color: yellow; font-size:8pt;">

     

              <a id="{$CommentUniqId}x" href="BLOCKED SCRIPTchangeDisplayState('{$CommentUniqId}x','{$CommentUniqId}','comdata')">

                    <sup style="color: green; background-color: grey; font-size:10pt;">c*</sup>

              </a>

     

            </span>

            <div id="{$CommentUniqId}" style="display:none">

     <xsl:apply-templates select="//w:comment[@w:id = $CommentId]"/>

    </div>

 </xsl:if>

  </xsl:template>

  <!--Template to process the "CommentRange-  w:commentRangeStart" Node-->

  <xsl:template match="w:comment">

  <xsl:if test="not($blnPublish='true')">

    <table border="1" style="color: green; background-color: yellow; font-size:10pt;">

      <tr>

        <td>

          <b> initials:</b>

        </td>

        <td>

          <xsl:value-of select="@w:initials"/>;

        </td>

      </tr>

      <tr>

        <td>

          <b>author:</b>

        </td>

        <td>

          <xsl:value-of select="@w:author"/>;

        </td>

      </tr>

      <tr>

        <td>

          <b>DateTime:</b>

        </td>

        <td>

          <xsl:value-of select="@w:date"/>;

        </td>

      </tr>

      <tr>

        <td>

          <b>Comments:</b>

        </td>

        <td>

          <xsl:apply-templates select="w:p"/>

        </td>

      </tr>

    </table>

    </xsl:if>

      </xsl:template>

</xsl:stylesheet>

  

The word document (“sampleDoc.docx”) looks like this

Figure 1: SampleDoc.docx

 

 

On running the application, the start up page is loaded.

 

Figure2: Upload Document screen

 

 

 

  

Select the file for upload using the”Browse” button.

 

Leave “Publish File” unchecked: Check it only if you want to ignore the revisions/comments made by the user.

 

Click “Start Converting to HTML” button.

 

Figure3: Processing Screen

 

 

This screen shows the user that the conversion of HTML is taking place.

 

Figure 4: Converted HTML Display

 

 

 

Let’s analyze the Generated HTML file shown above.

 

The html file tracks the changes made, both insertions and deletions.

 

Figure 5: Mouse-Over Display—who did this?

 

 

 

Moving the mouse over the yellow-marked “?*” displays the username who made the change.

 

Figure 6: Mouse-Over Display—what was the comment?

 

 

 

Moving the mouse over the yellow-marked “c*” display the comment.

 

 

Figure 7: Mouse-Click Display—what was the comment and who commented it?

 

 

Clicking on the yellow-marked “c*” displays the comment and details of who commented it .

After clicking the yellow-marked “c*” is replaced by an yellow-marked “hide tbl”.

 

On Click of “hide tbl” – back to sequential readable text.

 

Figure 8: Publish file (Remove changes made)

 

Check publish file and upload the same document, to find the changes removed.

 

Figure9: HTML file with changes removed

 

 

 

Restrictions: Don’t use the browser-back button (might throw an error).

 

Hope this helps.

 

Attachment: AsynchronousProcessing_downloads.zip
  • Could you please correct the image links.  Thanks.
Page 1 of 1 (1 items)