Field.Unlink removes content of header and footer using C#

I have a word document with some merged fields, when I convert the IF fields, the output document loses the previous header and footer.

I follow the example codes below:
compositeNode.Range.Fields.Cast().Where(f => f.Type == targetFieldType).ToList().ForEach(f => f.Unlink());

from below link: Working with Hyperlinks in C#|Aspose.Words for .NET

Can you please check whether the Unlink() method of the Field remove all header/footer? Is there any way keep the existing header and footer when convert the IF Field to the text?

Thanks
Peng

@peng_dai

To ensure a timely and accurate response, please attach the following resources here for testing:

  • Your input Word document.
  • Please attach the output Word file that shows the undesired behavior.
  • Please attach the expected output Word file that shows the desired behavior.
  • Please create a standalone console application ( source code without compilation errors ) that helps us to reproduce your problem on our end and attach it here for testing.

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

PS: To attach these resources, please zip and upload them.

ForAspose.zip (7.0 MB)
@tahir.manzoor
I found this was caused by different Header/footer sections in the document.
Please see below step to replicate:

  1. Please rename the two [Before]Application-WithDifferentHeaderSections.docx and [Before]Application-WithSameHeaderFooter.docx to the test.docx (there is an example in the folder), and put in the c:\temp folder
  2. Run the application
  3. The expected result is “Excpected-[After]Application-WithHeaderFooter.docx” which is the result form [Before]Application-WithSameHeaderFooter.docx
  4. The another “[After]Application-WithDifferentHeaderFooter.docx” is the wrong result from [Before]Application-WithDifferentHeaderSections.docx

So if the document contains two different Header Sections, when convert the fields to static text by using below codes, it will lose the original header/footer on the page1 and page2:
compositeNode.Range.Fields.Cast().Where(f => f.Type == targetFieldType).ToList().ForEach(f => f.Unlink());

@peng_dai

We have tested the scenario using the latest version of Aspose.Words for .NET 20.1 and have not found the shared issue. Please check the attached output documents.
sample-docs.zip (118.2 KB)

@tahir.manzoor
Thanks for your reply. I used the same version .net 20.1 for Aspose.Words.
But I found the sample docs you attached, each page uses the same header/footer.
Can you please test the same document I attached before - [Before]Application-WithDifferentHeaderFooter.docx and see the result? As I said in my post, the issue only happened when the pages have different header sections.

Thanks for your help.section2 footer.JPG (4.0 KB)
section2 Header.JPG (5.9 KB)[Before]Application-WithDifferentHeaderSections.zip (23.0 KB)

@peng_dai

Your input document contains the section break inside IF field. When you remove the IF field, it will also removes the second section of document. Please check the attached image for detail. section break.png (23.8 KB)

so you mean the unlink() method actually removes the IF field.
Still not clear is why remove the section of document will change the Header/Footer in previous pages?

@peng_dai

Please open your document in MS Word. From ‘Home’ tab, under ‘Paragraph’ section, click show/hide paragraph mark. This will show paragraph mark and section breaks in your document.

Your document contains two pages. Please press Alt + F9 to see the section break. You will notice that it is part of IF field. You can check the output of IF field and other fields by updating them using F9 key.

Moreover, note that Aspose.Words mimics the behavior of MS Word. If you unlink the fields using MS Word by pressing Ctrl+Shift+F9, you will get the same output.

@tahir.manzoor
Thanks for your reply, I can reproduce the unlink with Ctrl+Shift+F9, and now I understand it was MS Word behavior, even though my issue is not fixed, at least know the root reason.

Thanks again for your help.

@peng_dai

Thanks for your feedback. If you want to keep the section break that is inside IF field, we suggest you please iterate over IF fields nodes and remove them except the paragraph that contains section break. Hope this helps you.

Hi @tahir.manzoor
Thanks for your suggestion. I spent some time these days to investigate your example according to your above suggestion: Aspose.Words.Examples.CSharp.DocumentExplorer. From this example, I can see how to loop through the paragraphs of the Section->Body.

But I have a few questions which are unclear:

  1. Does your suggestion - iterate over IF fields nodes mean cross sections to find all paragraphs inside the IF fields?
  2. How can I know which paragraphs need to be deleted according to the IF fields Run? Does that mean I need execute the IF field logic inside the c# codes to decide keep which paragraphs?

I can see the Section/Body/Paragraph structures from your example DocumentExplorer, but it will be great if you can provide a bit more guide or example.

From attached snapshot, you can see the [!FieldEnd!] is in another section. How can we delete all paragraphs between [!FieldStart!] (in section1) and [!FieldEnd!](in section 2) conditionally?
Thanks in advance.
PengThe First Part of IF Field in Section1.JPG (77.6 KB)
The Second Part of IF Field in Section2.JPG (82.3 KB)

@peng_dai

Following code example shows how to unlink all fields including IF fields and keep the sections in the document. Hope this helps you.

Document doc = new Document(MyDir + "Before - Copy.docx");

foreach (Field field in doc.Range.Fields)
{
    if (field.Type == FieldType.FieldIf)
        continue;
    else
        field.Unlink();
}

foreach (Field field in doc.Range.Fields)
{
    bool iscontainSection = isIFContainsSection(doc, field);

    if (iscontainSection == false)
        field.Unlink();
    else
    {
        //Unlink if field that contains the section break.
        ArrayList nodes = UnlinkIFfieldKeepingSection(doc, field);

        foreach (Node n in nodes)
        {
            n.Remove();
        }
    }
}

doc.Save(MyDir + "output.docx");

private static ArrayList UnlinkIFfieldKeepingSection(Document doc, Field field)
{
    Node node = field.Start;
    Node end = field.End;

    ArrayList nodes = new ArrayList();
    while (node != end)
    {
        node = node.NextPreOrder(doc);
        if (node == field.Separator)
        {
            break;
        }

        if (node.NodeType == NodeType.Section)
        {
            node = ((Section)node).Body.FirstChild;
        }

        if (node.NodeType == NodeType.Paragraph)
        {
            Paragraph paragraph = (Paragraph)node;
            if (!paragraph.IsEndOfSection)
            {
                nodes.Add(node);
            }
        }
        else
            nodes.Add(node);
    }
    nodes.Add(field.Separator);
    nodes.Add(field.End);
    return nodes;
}

private static bool isIFContainsSection(Document doc, Field field)
{
    Boolean iscontainSection = false;
    if (field.Type == FieldType.FieldIf)
    {
        //Check if field contains the section break;
        Node node = field.Start;
        Node end = field.End;
        while (node != end)
        {
            node = node.NextPreOrder(doc);
            if (node.NodeType == NodeType.Paragraph)
            {
                Paragraph paragraph = (Paragraph)node;
                if (paragraph.IsEndOfSection)
                {
                    iscontainSection = true;
                    break;
                }
            }
        }
    }

    return iscontainSection;
}

Hi @tahir.manzoor
Thanks for your example.
The codes exactly removed the IF fields and keep the section.
But seems it lost the IF field logic – it simply remove all paragraphs between Start of IF and End of IF, but not execute the IF logic.

Please see the snapshot before execution and after, it keeps the section paragraph, and remove the other paragraphs of IF.

I also attached the test.docx file for your testing. The expected result should be the result after IF logic, so it should contain only 2 pages, the text: emptyRespondent5 Empty

Now it only display the text “this is Respondent5 name” from Else part of last IF field.
TestFileAndCompareResult.zip (134.9 KB)

Also your example doesn’t consider the multiple IF fields, it will only keep the last IF field. I fixed this in my attached example.
But can you please help me address below questions:

  1. How to display IFField.Display which is a string text, or can I add or append a paragraph whose text is set to IFField.Display?
  2. More challenge is : the section break is inside the ELSE statement, how can we conditionally display the break section?AsposeWordsMergeFieldsToTextDemo1.zip (7.1 MB)

@peng_dai

Please note that a field in a Word document is a complex structure consisting of multiple nodes that include field start, field code, field separator, field result and field end. Fields can be nested, contain rich content and span multiple paragraphs or sections in a document.

The Start, Separator and End properties point to the field start, separator and end nodes of the field respectively. The content between the field start and separator is the field code. The content between the field separator and field end is the field result.

You can use the same logic shared in my previous post to remove the content of field according to your requirement.

Hi @tahir.manzoor
Thanks for your reply!
Your tips: The content between the field separator and end is the field result. is helpful.

I agree the field is the complex structure, as it maybe nested, so it is challenge to figure out each field structure.

Anyway, appreciate your patient and example codes.
Thanks.