Building new document from old document Table of Contents collection pulled from an XML file

Hey, I have an XML file that I have created from reading the table of contents of a first document with the following layout:

<Section>
<Headers>
  <Header>
    <HeaderNum>2.1</HeaderNum>
    <HeaderText>Testing</HeaderText>
    <SubHeadings>
      <SubHeading>
        <SubheadingNumber>2.1.1</SubheadingNumber>
        <SubHeadingText>Text here</SubHeadingText> 
  </SubHeading>
</SubHeadings>
  </Header>
      <Header>
        <HeaderNum>2.2</HeaderNum>
        <HeaderText>Testing 2</HeaderText>
        <SubHeadings>
          <SubHeading>
            <SubheadingNumber>2.2.1</SubheadingNumber>
            <SubHeadingText>Text here</SubHeadingText>
          </SubHeading>
          <SubHeading>
            <SubheadingNumber>2.2.2</SubheadingNumber>
            <SubHeadingText>Subheading text here</SubHeadingText>
          </SubHeading>
        </SubHeadings>
      </Header>

The XML file has been deserialized and its contents stored in a collection that has the same layout as the original document.

I want to construct a new document from this collection, which includes three classes. A list of sections, which includes a list of headers, which in-turn each include a list of subHeadings.

Headers are created from Database tables elsewhere, however. So when the new document is constructed, new headers will be populated into the list, but the majority of the Table of Contents list will stay the same as the original document, barring a few near headers/subHeadings.

Is it possible to iterate over a collection such as this, programmatically creating new Sections, Headers and SubHeadings throughout a document in the same order as they have been stored in the collection?

I would simply copy the old document, but once the old document has been translated, that will no longer be optional and the new document is required to follow the same order of segments as the previous, but the contents of each section may have changed.

Please let me know if you would like me to clarify anything in my wording. Help is much appreciated, thank you!

@casperf11,

Thanks for your inquiry. To ensure a timely and accurate response, please ZIP and attach the following resources here for testing:

  • A simplified input Word document you have created this XML from
  • The actual XML file
  • Your expected DOCX document showing the final output that you would like to build from this XML. You can create expected document by using Microsoft Word.

As soon as you get these pieces of information ready, we will start further investigation into your scenario and provide you more information. Thanks for your cooperation.

Unfortunately, the documents are sensitive so I don’t think it’s best for me to share them. However, I got this working by adding the elements from this forum post to a collection, and then iterating over them with foreach, and then adding the results to basic objects in a nested manner, with a few case statements etcetera. Then I just used XmlSerializer to create and read from the file. I hope that’s helpful to people in the future!

However, I do have a separate issue and I hope it’s alright for me to ask here.

Is it possible to place a clone of an existing table after using a builder method? For example:

var table = (Table)doc.GetChild(NodeType.Table, 0, true);
var tableClone = (Table)table.Clone(true)
foreach(var object in list)
{
    builder.Write(object.text);
    // some logic to get table from database where name matches object.tableText
    // **insert tableClone here?**
    // populate tableClone with database object
}

@casperf11,

Yes, you can clone a Table and then insert the cloned Table at any valid location in Document hierarchy in DOM (document object model).

Thank you, can I do something like:

builder.Write(text);
table.ParentNode.InsertAfter(tableClone, builder.CurrentNode);

I’m having trouble getting this inserted whilst using the builder.

@casperf11,

You can insert cloned Tables in document without using DocumentBuilder. For example, please see these sample input/output word documents (tables-clone.zip (19.2 KB)) and try running the following code:

Document doc = new Document("D:\\temp\\tables.docx");

Table table = doc.FirstSection.Body.Tables[0];

Table clone1 = (Table)table.Clone(true);
Table clone2 = (Table)table.Clone(true);
Table clone3 = (Table)table.Clone(true);
Table clone4 = (Table)table.Clone(true);

Paragraph targetPara = doc.FirstSection.Body.Paragraphs[0];
targetPara.ParentNode.InsertAfter(clone1, targetPara);

targetPara = doc.FirstSection.Body.Paragraphs[1];
targetPara.ParentNode.InsertAfter(clone2, targetPara);

targetPara = doc.FirstSection.Body.Paragraphs[2];
targetPara.ParentNode.InsertAfter(clone3, targetPara);

targetPara = doc.FirstSection.Body.Paragraphs[3];
targetPara.ParentNode.InsertAfter(clone4, targetPara);

doc.Save("D:\\temp\\18.9.docx");

Hope, this helps.

1 Like

Thank you for the reply.

Unfortunately, I am using the builder to place other elements into a document, and need to place a table underneath the new element made by the builder, so placing a clone of a table underneath the original won’t be too useful for me :frowning:

Is it possible instead to store a template table at a certain page in the document, and then create a clone underneath the newest element that the builder has placed?

So something like:

// insert empty tableClone on page 7 here
foreach (var tableTitle in tables)
{
    builder.write(tableTitle)
    // place tableClone under latest builder element here
    // populate table from database here
}

@casperf11,

Please ZIP and attach your simplified input Word document and your expected document showing the desired output here for testing. Please create expected document by using MS Word. We will investigate the structure of your expected document and provide you code to achieve the same by using Aspose.Words.

1 Like

Thank you, I’ve attached my input and what my expected should look like.

Aspose Input-Output.zip (26.6 KB)

@casperf11,

A Table is a block-level node. You can get the parent Paragraph of current node and then insert Table after/before that Paragraph.

Paragraph para = (Paragraph) builder.CurrentNode.GetAncestor(NodeType.Paragraph); 
if (para != null)
{
    // to do
}
1 Like