wordpress hit counter
Re: How to update word (.docx) TOC - WordprocessingML - Formats - OpenXML Developer

Re: How to update word (.docx) TOC

Formats

Discussions about working with different Open XML Formats

How to update word (.docx) TOC

  • rated by 0 users
  • This post has 19 Replies |
  • 1 Follower
  • Can anyone tell me how to update word table of contents using Open XML SDK 2.0 dynamically.

  • SDK cannot do it automatically or dynamically, but there's a workaround for you: use dirty value to indicate Word client to do it when you open the document. here's the discusstion: http://social.msdn.microsoft.com/Forums/en-US/oxmlsdk/thread/29199b44-f033-466a-a471-6bdcfeb47e41
  • You can use this code.

    /// <summary>
    /// returns title paragraphs of genereated doc fro creating toc hyperlink
    /// </summary>

    private IEnumerable<XElement> TitleParagraphsElements(XDocument mainDocument)
            {
                
                IEnumerable<XElement> results =
                  mainDocument.Descendants().Where
                  (
                      tag =>
                          tag.Name == ns + "p" &&
                          tag.Descendants(ns + "t").Count() > 0 &&
                          tag.Descendants().Where
                          (
                            tag2 =>
                                tag2.Name == ns + "pStyle" &&
                                (
                                    tag2.Attribute(ns + "val").Value == "Heading1" ||
                                    tag2.Attribute(ns + "val").Value == "Heading2" ||
                                    tag2.Attribute(ns + "val").Value == "Heading3" ||
                                    tag2.Attribute(ns + "val").Value == "Heading4" ||
                                    tag2.Attribute(ns + "val").Value == "Heading5" ||
                                    tag2.Attribute(ns + "val").Value == "Heading6"
                                )
                          ).Count() > 0
                  );

                return results;
            }

    /// <summary>
    /// Generate the Table Of Contents(TOC) of the document
    /// </summary>

            private void GenerateTOC(XDocument xmlMainDocument, XElement TOCRefNode)
            {
                int bookMarkIdCounter = 0;
                int maxHeading = 1;
                int tempheading = 1;

                //  sdtContent, will contain all the paragraphs used in the TOC
                XElement sdtContent = new XElement(ns + "sdtContent");
                String strContentHdr = "";
                XElement xContentHdr = TOCRefNode.Elements(ns + "sdtContent").First().Descendants().Where(
                    tag =>
                        tag.Name == ns + "p" &&
                        tag.Descendants().Where
                        (
                            tag2 =>
                                tag2.Name == ns + "pStyle" &&
                                tag2.Attribute(ns + "val").Value == "TOCHeading"
                        ).Count() > 0
                    ).FirstOrDefault();

                if (xContentHdr != null)
                    strContentHdr = xContentHdr.Descendants(ns + "t").FirstOrDefault().Value;

                //  build the title of the TOC and add it in the sdtContent element, and
                //  some information regarding the attributes of the TOC
                xContentHdr.Add(

                            new XElement(ns + "r",
                                new XElement(ns + "fldChar",
                                        new XAttribute(ns + "fldCharType", "begin"))),
                            new XElement(ns + "r",
                                new XElement(ns + "instrText",
                                    new XAttribute(XNamespace.Xml + "space", "preserve"),
                                    "TOCLIMIT")),
                            new XElement(ns + "r",
                                new XElement(ns + "fldChar",
                                    new XAttribute(ns + "fldCharType", "separate"))));
                sdtContent.Add(new XElement(xContentHdr));

               

                //  for each title found it in the document, we have to wrap the run inside of it,
                //  with a bookmark, this bookmark will have an id which will work as an anchor,
                //  for link references in the TOC
                foreach (XElement titleParagraph in TitleParagraphsElements(xmlMainDocument))
                {
                    string bookmarkName = bookmarkNamePrefix + bookMarkIdCounter;
                    XElement bookmarkStart =
                        new XElement(ns + "bookmarkStart",
                            new XAttribute(ns + "id", bookMarkIdCounter),
                            new XAttribute(ns + "name", bookmarkName));
                    XElement bookmarkEnd =
                        new XElement(ns + "bookmarkEnd",
                            new XAttribute(ns + "id", bookMarkIdCounter));

                    //  wrap the run with bookmarkStart and bookmarkEnd
                    titleParagraph.AddFirst(bookmarkStart);
                    titleParagraph.Add(bookmarkEnd);

                    //  get the name of the style of the parapgraph of the title, and for each one,
                    //  choose a style to add in the paragraph inside the TOC
                    string referenceTitleStyle = "";
                    switch (titleParagraph.Descendants(ns + "pStyle").First().Attribute(ns + "val").Value)
                    {
                        case "Heading1":
                            {
                                referenceTitleStyle = "TOC1";
                                tempheading = 1;
                                break;
                            }
                        case "Heading2":
                            {
                                referenceTitleStyle = "TOC2";
                                tempheading = 2;
                                break;
                            }
                        case "Heading3":
                            {
                                referenceTitleStyle = "TOC3";
                                tempheading = 3;
                                break;
                            }
                        case "Heading4":
                            {
                                referenceTitleStyle = "TOC4";
                                tempheading = 4;
                                break;
                            }
                        case "Heading5":
                            {
                                referenceTitleStyle = "TOC5";
                                tempheading = 5;
                                break;
                            }
                        case "Heading6":
                            {
                                referenceTitleStyle = "TOC6";
                                tempheading = 6;
                                break;
                            }
                    }
                   

                    string entryContent = "";
                    IEnumerable<XElement> owTList = titleParagraph.Descendants(ns + "t");
                    foreach (XElement entryElement in owTList)
                    {
                        entryContent += (entryElement == null ? string.Empty : entryElement.Value);
                    }

                    XElement TOCElement = null;
                    XElement tempTOCElement = TOCRefNode.Elements(ns + "sdtContent").First().Descendants().Where(
                    tag =>
                        tag.Name == ns + "p" &&
                        tag.Descendants().Where
                        (
                            tag2 =>
                                tag2.Name == ns + "pStyle" &&
                                tag2.Attribute(ns + "val").Value == referenceTitleStyle
                        ).Count() > 0
                    ).FirstOrDefault();

                    if (tempTOCElement != null)
                    {
                        if (maxHeading < tempheading)
                            maxHeading = tempheading;

                        TOCElement = new XElement(tempTOCElement);
                        //delete instrText which contains TOC 1-n
                        XElement instrTextTOC = TOCElement.Descendants().Where(
                                tag =>
                                    tag.Name == ns + "r" &&
                                    tag.Descendants().Where(
                                        tag2=>
                                            tag2.Name == ns + "instrText" &&
                                            tag2.Value.Contains(@"TOC \o ")
                                    ).Count() > 0
                                   
                            ).FirstOrDefault();
                        if (instrTextTOC != null)
                        {
                            instrTextTOC.ElementsAfterSelf(ns + "r").Remove();
                            instrTextTOC.ElementsBeforeSelf(ns + "r").Remove();
                            instrTextTOC.Remove();
                        }

                        //get hyperlink node
                        XElement hyperlink = TOCElement.Descendants().Where(
                                tag=>
                                    tag.Name == ns + "hyperlink"

                            ).FirstOrDefault();
                        //update anchor attribute value
                        hyperlink.Attribute(ns + "anchor").Value = bookmarkName;
                       
                        //get entry content node
                        XElement contentNode = hyperlink.Descendants().Where(
                                tag=>
                                    tag.Name == ns + "r" &&
                                    tag.Descendants().Where(
                                        tag2=>
                                            tag2.Name ==ns + "rStyle" &&
                                            tag2.Attribute(ns +"val").Value == "Hyperlink"
                                    ).Count() > 0 &&
                                    tag.Elements(ns+"t").Count() > 0

                            ).FirstOrDefault().Elements(ns+"t").FirstOrDefault();

                        contentNode.Value = entryContent;

                        //update PAGEREF value
                        XElement instrText = TOCElement.Descendants().Where(
                                tag=>
                                    tag.Name == ns + "instrText" &&
                                    tag.Value.Contains("PAGEREF ")
                            ).FirstOrDefault();
                        if (instrText != null)
                        {
                            instrText.Value = " PAGEREF " + bookmarkName + @" \h ";
                        }

                        sdtContent.Add(TOCElement);
                        bookMarkIdCounter++;
                    }
                   
                   
                }

                sdtContent.Descendants().Where(
                    tag =>
                        tag.Name == ns + "instrText" &&
                        tag.Value.Contains("TOCLIMIT")
                    ).FirstOrDefault().Value = String.Format(@" TOC \o ""1-{0}"" \h \z \u ",maxHeading);

                sdtContent.Add(
                    new XElement(ns + "p",
                        new XElement(ns + "r",
                            new XElement(ns + "fldChar",
                                new XAttribute(ns + "fldCharType", "end")))));

                //  Finish the xml construction of the TOC
                XElement TOC =
                    new XElement(ns + "sdt",
                        new XElement(ns + "sdtPr",
                            new XElement(ns + "docPartObj",
                                new XElement(ns + "docPartGallery",
                                    new XAttribute(ns + "val", "Table of Contents")),
                                new XElement(ns + "docPartUnique"))),
                        sdtContent);

                //  add it to the original document
               
                IEnumerable<XElement> tocNodes = xmlMainDocument.Descendants().Where
                  (
                      tag =>
                          tag.Name == ns + "sdt" &&
                          tag.Descendants(ns + "sdtContent").Count() > 0 &&
                          tag.Descendants().Where
                          (
                            tag2 =>
                                tag2.Name == ns + "p" &&
                                tag2.Descendants().Where
                                (
                                    tag3 =>
                                        tag3.Name == ns + "pStyle" &&
                                            (
                                                tag3.Attribute(ns + "val").Value == "TOCHeading"
                                            )
                                ).Count() > 0

                          ).Count() > 0
                  );

               
                TOCRefNode.ReplaceWith(TOC);

            }
  • Hi prosantak,

    I see your code create the TOC, but is the TOC able to update the hyperlinks automatically?

  • Hi goodol

    Yes, it will update the hyperlink automatically when the document open.

    Thanks

    Prosanta

  • Hi Prosanta,
     
    Do you mean you need to leverage the Word application to open the document for refreshing?
    Could you tell me the philosophy how you make the automatic refresh happens. Is there some dirty values within to indicate the application refresh? Thanks:)
  • goodol:
    ... but there's a workaround for you: use dirty value to indicate Word client to do it when you open the document. here's the discusstion: http://social.msdn.microsoft.com/Forums/en-US/oxmlsdk/thread/29199b44-f033-466a-a471-6bdcfeb47e41


    Unfortunately, it doesn't help me. Word 2007 doesn't update content of TOC on open :(

    I experimented with other field types (AUTHOR, FILENAME), Word 2007 doesn't update these fields too.
  • Hi goodol

    The logic behind TOC generation is very simple. It opens the docx file using openxml.

    1. Find the paragraph marks with diffrent heading style
    2. Sets a hyperlink there
    3. Update TOC entry

    But in this case page numbers will not updated. When user opens the generated document, he/she have to update page numbers manually. Also you can set w:dirty attribute in TOC, but it will prompt for updation when the document is open first time. In my case I didn't use the w:diry attribute. I leave it to user to update page numbers manually.

    Thanks
    Prosanta

  • What is "ns" ,"bookmarkNamePrefix" and  XDocument xmlMainDocument, XElement TOCRefNode in the code?

     

    And also

    sdtContent.Descendants().Where(
                    tag =>
                        tag.Name == ns + "instrText" &&
                        tag.Value.Contains("TOCLIMIT")
                    ).FirstOrDefault().Value = String.Format(@" TOC \o ""1-{0}"" \h \z \u ",maxHeading);


    What is TOCLIMIT ?

     

    i found public static XNamespace ns = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";

  • Here is the complete solution

     

     using (WordprocessingDocument WorDocument = WordprocessingDocument.Create(@"C:\TestDocuments\Business Case Document.docx", WordprocessingDocumentType.Document))
                {
                    // Add a new main document part.
                    MainDocumentPart mainPart = WorDocument.AddMainDocumentPart();
                    //Create Document tree for simple document.
                    mainPart.Document = new Document();
                    //Create Body (this element contains other elements that we want to include
                    Body body = new Body();
                   

                    //Save changes to the main document part.
                    mainPart.Document.Append(body);
                   
                    XDocument xmlXdocument = XDocument.Parse(mainPart.Document.InnerXml);
                    IEnumerable<XElement> xmlelement = xmlXdocument.Descendants(ns + "sdt");
                    XElement TOCRefNode = xmlelement.First();
                    GenerateTOC(xmlXdocument, TOCRefNode);

                    mainPart.Document.InnerXml = xmlXdocument.ToString();
                   
                    mainPart.Document.Save();
                    WorDocument.Close();

                }

      #region TOC Creation
                /// <summary>
                /// returns title paragraphs of genereated doc fro creating toc hyperlink
                /// </summary>
            private static IEnumerable<XElement> TitleParagraphsElements(XDocument mainDocument)
            {
                IEnumerable<XElement> results = mainDocument.Descendants().Where
                  (
                      tag =>
                          tag.Name == ns + "p" &&
                          tag.Descendants(ns + "t").Count() > 0 &&
                          tag.Descendants().Where
                          (
                            tag2 =>
                                tag2.Name == ns + "pStyle" &&
                                (
                                    tag2.Attribute(ns + "val").Value == "Head1" ||
                                    tag2.Attribute(ns + "val").Value == "Head2" ||
                                    tag2.Attribute(ns + "val").Value == "Head3" ||
                                    tag2.Attribute(ns + "val").Value == "Head4" ||
                                    tag2.Attribute(ns + "val").Value == "Head5" ||
                                    tag2.Attribute(ns + "val").Value == "Head6"
                                )
                          ).Count() > 0
                  );

                return results;
            }

            private static  void GenerateTOC(XDocument xmlMainDocument, XElement TOCRefNode)
            {
                int bookMarkIdCounter = 0;
                int maxHeading = 1;
                int tempheading = 1;

                //  sdtContent, will contain all the paragraphs used in the TOC
                XElement sdtContent = new XElement(ns + "sdtContent");
                String strContentHdr = "";
                XElement xContentHdr = TOCRefNode.Elements(ns + "sdtContent").First().Descendants().Where(
                    tag =>
                        tag.Name == ns + "p" &&
                        tag.Descendants().Where
                        (
                            tag2 =>
                                tag2.Name == ns + "pStyle" &&
                                tag2.Attribute(ns + "val").Value == "TOCHeading"
                        ).Count() > 0
                    ).FirstOrDefault();

                if (xContentHdr != null)
                    strContentHdr = xContentHdr.Descendants(ns + "t").FirstOrDefault().Value;

                //  some information regarding the attributes of the TOC
                xContentHdr.Add(

                            new XElement(ns + "r",
                                new XElement(ns + "fldChar",
                                        new XAttribute(ns + "fldCharType", "begin"))),
                            new XElement(ns + "r",
                                new XElement(ns + "instrText",
                                    new XAttribute(XNamespace.Xml + "space", "preserve"),
                                    "TOCLIMIT")),
                            new XElement(ns + "r",
                                new XElement(ns + "fldChar",
                                    new XAttribute(ns + "fldCharType", "separate"))));
                sdtContent.Add(new XElement(xContentHdr));


                //  for each title found it in the document, we have to wrap the run inside of it,
                //  with a bookmark, this bookmark will have an id which will work as an anchor,
                //  for link references in the TOC
                foreach (XElement titleParagraph in TitleParagraphsElements(xmlMainDocument))
                {
                    string bookmarkName = "_TOC" + bookMarkIdCounter;
                    XElement bookmarkStart =
                        new XElement(ns + "bookmarkStart",
                            new XAttribute(ns + "id", bookMarkIdCounter),
                            new XAttribute(ns + "name", bookmarkName));
                    XElement bookmarkEnd =
                        new XElement(ns + "bookmarkEnd",
                            new XAttribute(ns + "id", bookMarkIdCounter));

                    //  wrap the run with bookmarkStart and bookmarkEnd
                    titleParagraph.AddFirst(bookmarkStart);
                    titleParagraph.Add(bookmarkEnd);

                    //  get the name of the style of the parapgraph of the title, and for each one,
                    //  choose a style to add in the paragraph inside the TOC
                    string referenceTitleStyle = "";
                    switch (titleParagraph.Descendants(ns + "pStyle").First().Attribute(ns + "val").Value)
                    {
                        case "Head1":
                            {
                                referenceTitleStyle = "TOC1";
                                tempheading = 1;
                                break;
                            }
                        case "Head2":
                            {
                                referenceTitleStyle = "TOC2";
                                tempheading = 2;
                                break;
                            }
                        case "Head3":
                            {
                                referenceTitleStyle = "TOC3";
                                tempheading = 3;
                                break;
                            }
                        case "Head4":
                            {
                                referenceTitleStyle = "TOC4";
                                tempheading = 4;
                                break;
                            }
                        case "Head5":
                            {
                                referenceTitleStyle = "TOC5";
                                tempheading = 5;
                                break;
                            }
                        case "Head6":
                            {
                                referenceTitleStyle = "TOC6";
                                tempheading = 6;
                                break;
                            }
                    }


                    string entryContent = "";
                    IEnumerable<XElement> owTList = titleParagraph.Descendants(ns + "t");
                    foreach (XElement entryElement in owTList)
                    {
                        entryContent += (entryElement == null ? string.Empty : entryElement.Value);
                    }

                    XElement TOCElement = null;
                    XElement tempTOCElement = TOCRefNode.Elements(ns + "sdtContent").First().Descendants().Where(
                    tag =>
                        tag.Name == ns + "p" &&
                        tag.Descendants().Where
                        (
                            tag2 =>
                                tag2.Name == ns + "pStyle" &&
                                tag2.Attribute(ns + "val").Value == referenceTitleStyle
                        ).Count() > 0
                    ).FirstOrDefault();

                    if (tempTOCElement != null)
                    {
                        if (maxHeading < tempheading)
                            maxHeading = tempheading;

                        TOCElement = new XElement(tempTOCElement);
                        //delete instrText which contains TOC 1-n
                        XElement instrTextTOC = TOCElement.Descendants().Where(
                                tag =>
                                    tag.Name == ns + "r" &&
                                    tag.Descendants().Where(
                                        tag2 =>
                                            tag2.Name == ns + "instrText" &&
                                            tag2.Value.Contains(@"TOC \o ")
                                    ).Count() > 0

                            ).FirstOrDefault();
                        if (instrTextTOC != null)
                        {
                            instrTextTOC.ElementsAfterSelf(ns + "r").Remove();
                            instrTextTOC.ElementsBeforeSelf(ns + "r").Remove();
                            instrTextTOC.Remove();
                        }

                        //get hyperlink node
                        XElement hyperlink = TOCElement.Descendants().Where(
                                tag =>
                                    tag.Name == ns + "hyperlink"

                            ).FirstOrDefault();
                        //update anchor attribute value
                        hyperlink.Attribute(ns + "anchor").Value = bookmarkName;

                        //get entry content node
                        XElement contentNode = hyperlink.Descendants().Where(
                                tag =>
                                    tag.Name == ns + "r" &&
                                    tag.Descendants().Where(
                                        tag2 =>
                                            tag2.Name == ns + "rStyle" &&
                                            tag2.Attribute(ns + "val").Value == "Hyperlink"
                                    ).Count() > 0 &&
                                    tag.Elements(ns + "t").Count() > 0

                            ).FirstOrDefault().Elements(ns + "t").FirstOrDefault();

                        contentNode.Value = entryContent;

                        //update PAGEREF value
                        XElement instrText = TOCElement.Descendants().Where(
                                tag =>
                                    tag.Name == ns + "instrText" &&
                                    tag.Value.Contains("PAGEREF ")
                            ).FirstOrDefault();
                        if (instrText != null)
                        {
                            instrText.Value = " PAGEREF " + bookmarkName + @" \h ";
                        }

                        sdtContent.Add(TOCElement);
                        bookMarkIdCounter++;
                    }


                }

                sdtContent.Descendants().Where(
                    tag =>
                        tag.Name == ns + "instrText"
                        &&
                        tag.Value.Contains("TOCLIMIT")
                    ).FirstOrDefault().Value = String.Format(@"TOC \o ""1-{0}"" \h \z \u ", maxHeading);

                sdtContent.Add(
                    new XElement(ns + "p",
                        new XElement(ns + "r",
                            new XElement(ns + "fldChar",
                                new XAttribute(ns + "fldCharType", "end")))));

                //  Finish the xml construction of the TOC
                XElement TOC =
                    new XElement(ns + "sdt",
                        new XElement(ns + "sdtPr",
                            new XElement(ns + "docPartObj",
                                new XElement(ns + "docPartGallery",
                                    new XAttribute(ns + "val", "Table of Contents")),
                                new XElement(ns + "docPartUnique"))),
                        sdtContent);

                //  add it to the original document

                IEnumerable<XElement> tocNodes = xmlMainDocument.Descendants().Where
                  (
                      tag =>
                          tag.Name == ns + "sdt" &&
                          tag.Descendants(ns + "sdtContent").Count() > 0 &&
                          tag.Descendants().Where
                          (
                            tag2 =>
                                tag2.Name == ns + "p" &&
                                tag2.Descendants().Where
                                (
                                    tag3 =>
                                        tag3.Name == ns + "pStyle" &&
                                            (
                                                tag3.Attribute(ns + "val").Value == "TOCHeading"
                                            )
                                ).Count() > 0

                          ).Count() > 0
                  );

                TOCRefNode.ReplaceWith(TOC);

            }


            #endregion

  • @sukhwal
    its not working
    table of contents are not being updated automaticaly

    any idea?
  • It doesn't work too, and when I run this program the variable "xContentHdr" will be null.

    Can someone tell me what should be in "TOCRefNode"?

    I want to know whether this prograom just update the exist TOC but not create it?

  • Check out: http://blogs.msdn.com/brian_jones/archive/2010/02/09/leveraging-the-power-of-word-automation-services-and-the-open-xml-sdk.aspx
  • LMars:
    goodol:
    ... but there's a workaround for you: use dirty value to indicate Word client to do it when you open the document. here's the discusstion: http://social.msdn.microsoft.com/Forums/en-US/oxmlsdk/thread/29199b44-f033-466a-a471-6bdcfeb47e41
    Unfortunately, it doesn't help me. Word 2007 doesn't update content of TOC on open :( I experimented with other field types (AUTHOR, FILENAME), Word 2007 doesn't update these fields too.
    Somehow I don't get how is it possible to use altChunks to merge the paper writing documents for leveraging content in other formats.
  • Hi,

    It is working fine. Check out the following Steps:

    • Use the TOC Region code as written in the ealier blog
    • Use a template to create the doc. Instead of creating a new doc use exisiting doc template.To create a new template follow the steps:
      • Create a new doc in Word 2007
      • The doc template should contain a TOC. To add toc in word 2007 follow the steps:
        • Reference-->Table of content-->Automatic table 1
      • Now Just below the Table of content Add a Header(Heading1) and write something.
      • Update the TOC.Chck the TOCshould be updated
      • Delete the Header, which you have written. Do not touch the TOC.
      • Save the Doc an close it.
    • Now follow the following code:

    static XNamespace ns = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
       
    public void generateWordDocument()
            {
         WindowsIdentity currentUserIdentity = (WindowsIdentity)User.Identity;
                WindowsImpersonationContext impersonationContext = currentUserIdentity.Impersonate();
                try
                {
             string fileName = currentUserIdentity.Name.Replace("\\", "_") + "_Report.docx";
                    string filePath = @"D:\Personals\Sudip\" + fileName;
                    File.Copy(@"D:\Personals\Sudip\Contents.docx", filePath);
      using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(filePath, true))
                    {
                        MainDocumentPart mainPart = wordDoc.MainDocumentPart;
     
          //Create Document tree for simple document.
                        mainPart.Document = new Document();
                        //Create Body (this element contains other elements that we want to include
                        Body body = new Body();
                   
          //This body should contain Headers.
         
                        //Save changes to the main document part.
                        mainPart.Document.Append(body);

          XDocument xmlXdocument = XDocument.Parse(mainPart.Document.InnerXml);
                        IEnumerable<XElement> xmlelement = xmlXdocument.Descendants(ns + "sdt");
                        XElement TOCRefNode = xmlelement.First();
                        GenerateTOC(xmlXdocument, TOCRefNode);

                        mainPart.Document.InnerXml = xmlXdocument.ToString();

                        mainPart.Document.Save();
          wordDoc.Close();
      }
      
         }
     }
     
    #region TOC Creation
                /// <summary>
                /// returns title paragraphs of genereated doc fro creating toc hyperlink
                /// </summary>
            private static IEnumerable<XElement> TitleParagraphsElements(XDocument mainDocument)
            {
                IEnumerable<XElement> results = mainDocument.Descendants().Where
                  (
                      tag =>
                          tag.Name == ns + "p" &&
                          tag.Descendants(ns + "t").Count() > 0 &&
                          tag.Descendants().Where
                          (
                            tag2 =>
                                tag2.Name == ns + "pStyle" &&
                                (
                                    tag2.Attribute(ns + "val").Value == "Head1" ||
                                    tag2.Attribute(ns + "val").Value == "Head2" ||
                                    tag2.Attribute(ns + "val").Value == "Head3" ||
                                    tag2.Attribute(ns + "val").Value == "Head4" ||
                                    tag2.Attribute(ns + "val").Value == "Head5" ||
                                    tag2.Attribute(ns + "val").Value == "Head6" ||
                                    tag2.Attribute(ns + "val").Value == "Heading1"||
                                    tag2.Attribute(ns + "val").Value == "Heading2"
                                )
                          ).Count() > 0
                  );

                return results;
            }

            private static  void GenerateTOC(XDocument xmlMainDocument, XElement TOCRefNode)
            {
                int bookMarkIdCounter = 0;
                int maxHeading = 1;
                int tempheading = 1;

                //  sdtContent, will contain all the paragraphs used in the TOC
                XElement sdtContent = new XElement(ns + "sdtContent");
                String strContentHdr = "";
                XElement xContentHdr = TOCRefNode.Elements(ns + "sdtContent").First().Descendants().Where(
                    tag =>
                        tag.Name == ns + "p" &&
                        tag.Descendants().Where
                        (
                            tag2 =>
                                tag2.Name == ns + "pStyle" &&
                                tag2.Attribute(ns + "val").Value == "TOCHeading"
                        ).Count() > 0
                    ).FirstOrDefault();

                if (xContentHdr != null)
                    strContentHdr = xContentHdr.Descendants(ns + "t").FirstOrDefault().Value;

                //  some information regarding the attributes of the TOC
                xContentHdr.Add(

                            new XElement(ns + "r",
                                new XElement(ns + "fldChar",
                                        new XAttribute(ns + "fldCharType", "begin"))),
                            new XElement(ns + "r",
                                new XElement(ns + "instrText",
                                    new XAttribute(XNamespace.Xml + "space", "preserve"),
                                    "TOCLIMIT")),
                            new XElement(ns + "r",
                                new XElement(ns + "fldChar",
                                    new XAttribute(ns + "fldCharType", "separate"))));
                sdtContent.Add(new XElement(xContentHdr));


                //  for each title found it in the document, we have to wrap the run inside of it,
                //  with a bookmark, this bookmark will have an id which will work as an anchor,
                //  for link references in the TOC
                foreach (XElement titleParagraph in TitleParagraphsElements(xmlMainDocument))
                {
                    string bookmarkName = "_TOC" + bookMarkIdCounter;
                    XElement bookmarkStart =
                        new XElement(ns + "bookmarkStart",
                            new XAttribute(ns + "id", bookMarkIdCounter),
                            new XAttribute(ns + "name", bookmarkName));
                    XElement bookmarkEnd =
                        new XElement(ns + "bookmarkEnd",
                            new XAttribute(ns + "id", bookMarkIdCounter));

                    //  wrap the run with bookmarkStart and bookmarkEnd
                    titleParagraph.AddFirst(bookmarkStart);
                    titleParagraph.Add(bookmarkEnd);

                    //  get the name of the style of the parapgraph of the title, and for each one,
                    //  choose a style to add in the paragraph inside the TOC
                    string referenceTitleStyle = "";
                    switch (titleParagraph.Descendants(ns + "pStyle").First().Attribute(ns + "val").Value)
                    {
                        case "Head1":
                            {
                                referenceTitleStyle = "TOC1";
                                tempheading = 1;
                                break;
                            }
                        case "Head2":
                            {
                                referenceTitleStyle = "TOC2";
                                tempheading = 2;
                                break;
                            }
                        case "Head3":
                            {
                                referenceTitleStyle = "TOC3";
                                tempheading = 3;
                                break;
                            }
                        case "Head4":
                            {
                                referenceTitleStyle = "TOC4";
                                tempheading = 4;
                                break;
                            }
                        case "Head5":
                            {
                                referenceTitleStyle = "TOC5";
                                tempheading = 5;
                                break;
                            }
                        case "Head6":
                            {
                                referenceTitleStyle = "TOC6";
                                tempheading = 6;
                                break;
                            }
              case "Heading1":
                            {
                                referenceTitleStyle = "TOC1";
                                tempheading = 6;
                                break;
                            }
                        case "Heading2":
                            {
                                referenceTitleStyle = "TOC2";
                                tempheading = 6;
                                break;
                            }
                    }


                    string entryContent = "";
                    IEnumerable<XElement> owTList = titleParagraph.Descendants(ns + "t");
                    foreach (XElement entryElement in owTList)
                    {
                        entryContent += (entryElement == null ? string.Empty : entryElement.Value);
                    }

                    XElement TOCElement = null;
                    XElement tempTOCElement = TOCRefNode.Elements(ns + "sdtContent").First().Descendants().Where(
                    tag =>
                        tag.Name == ns + "p" &&
                        tag.Descendants().Where
                        (
                            tag2 =>
                                tag2.Name == ns + "pStyle" &&
                                tag2.Attribute(ns + "val").Value == referenceTitleStyle
                        ).Count() > 0
                    ).FirstOrDefault();

                    if (tempTOCElement != null)
                    {
                        if (maxHeading < tempheading)
                            maxHeading = tempheading;

                        TOCElement = new XElement(tempTOCElement);
                        //delete instrText which contains TOC 1-n
                        XElement instrTextTOC = TOCElement.Descendants().Where(
                                tag =>
                                    tag.Name == ns + "r" &&
                                    tag.Descendants().Where(
                                        tag2 =>
                                            tag2.Name == ns + "instrText" &&
                                            tag2.Value.Contains(@"TOC \o ")
                                    ).Count() > 0

                            ).FirstOrDefault();
                        if (instrTextTOC != null)
                        {
                            instrTextTOC.ElementsAfterSelf(ns + "r").Remove();
                            instrTextTOC.ElementsBeforeSelf(ns + "r").Remove();
                            instrTextTOC.Remove();
                        }

                        //get hyperlink node
                        XElement hyperlink = TOCElement.Descendants().Where(
                                tag =>
                                    tag.Name == ns + "hyperlink"

                            ).FirstOrDefault();
                        //update anchor attribute value
                        hyperlink.Attribute(ns + "anchor").Value = bookmarkName;

                        //get entry content node
                        XElement contentNode = hyperlink.Descendants().Where(
                                tag =>
                                    tag.Name == ns + "r" &&
                                    tag.Descendants().Where(
                                        tag2 =>
                                            tag2.Name == ns + "rStyle" &&
                                            tag2.Attribute(ns + "val").Value == "Hyperlink"
                                    ).Count() > 0 &&
                                    tag.Elements(ns + "t").Count() > 0

                            ).FirstOrDefault().Elements(ns + "t").FirstOrDefault();

                        contentNode.Value = entryContent;

                        //update PAGEREF value
                        XElement instrText = TOCElement.Descendants().Where(
                                tag =>
                                    tag.Name == ns + "instrText" &&
                                    tag.Value.Contains("PAGEREF ")
                            ).FirstOrDefault();
                        if (instrText != null)
                        {
                            instrText.Value = " PAGEREF " + bookmarkName + @" \h ";
                        }

                        sdtContent.Add(TOCElement);
                        bookMarkIdCounter++;
                    }


                }

                sdtContent.Descendants().Where(
                    tag =>
                        tag.Name == ns + "instrText"
                        &&
                        tag.Value.Contains("TOCLIMIT")
                    ).FirstOrDefault().Value = String.Format(@"TOC \o ""1-{0}"" \h \z \u ", maxHeading);

                sdtContent.Add(
                    new XElement(ns + "p",
                        new XElement(ns + "r",
                            new XElement(ns + "fldChar",
                                new XAttribute(ns + "fldCharType", "end")))));

                //  Finish the xml construction of the TOC
                XElement TOC =
                    new XElement(ns + "sdt",
                        new XElement(ns + "sdtPr",
                            new XElement(ns + "docPartObj",
                                new XElement(ns + "docPartGallery",
                                    new XAttribute(ns + "val", "Table of Contents")),
                                new XElement(ns + "docPartUnique"))),
                        sdtContent);

                //  add it to the original document

                IEnumerable<XElement> tocNodes = xmlMainDocument.Descendants().Where
                  (
                      tag =>
                          tag.Name == ns + "sdt" &&
                          tag.Descendants(ns + "sdtContent").Count() > 0 &&
                          tag.Descendants().Where
                          (
                            tag2 =>
                                tag2.Name == ns + "p" &&
                                tag2.Descendants().Where
                                (
                                    tag3 =>
                                        tag3.Name == ns + "pStyle" &&
                                            (
                                                tag3.Attribute(ns + "val").Value == "TOCHeading"
                                            )
                                ).Count() > 0

                          ).Count() > 0
                  );

                TOCRefNode.ReplaceWith(TOC);

            }


            #endregion

     

     

Page 1 of 2 (20 items) 12