2

I am normalizing my docx document using the NormalizeXml function from the XML Powertools 2.2 with this code:

SimplifyMarkupSettings settings = new SimplifyMarkupSettings{
           NormalizeXml = true,
};

My goal is to search and replace variables, but the variables are not always in the same "Run Property" and as a result does not get replaced. I also do not want to disable the proofing in Office.

After running my program the docx file is corrupt and complains about styles when I try to open it (and the NormalizeXml function did not work or finish):

The XML Data is invalid according to the schema. Part:/word/styles.xml,Line 1, Column 0

I am using OpenXml 2.0 since OpenXml 2.5 needs .Net 4.5

I'm also using Office 2013.

When I use the OpenXml 2.0 Productivity Tool it picks up the error like this:

Error Node Type : Styles Error Part : /word/styles/xml Error Node Path : /w:styles1 Description : The Ignorable attribute is invalid - The value 'w14 w15' contains an invalid prefix that is not defined.

Here is what I see when I open styles.xml :

<?xml version="1.0" encoding="utf-8"?><w:styles mc:Ignorable="w14 w15" xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape">

I would like to keep the documents compatible between Office 2007/2010/2013.

At this stage I am considering searching for this "mc:Ignorable="w14 w15" attribute and doing an empty replace but there must be a better way to do this.

Thanks for any advice.

Albertus
  • 911
  • 2
  • 10
  • 19

3 Answers3

0

My temporary solution is to make sure the variables (and any characters used to detect the variable for example : #name#) in the document that needs to be replaced are of EXACTLY the same font so the "Run Properties" don't get broken up.

I am also using EditIx to make sure the variable is in ONE "Run Property", but this is not ideal as I want the users to add their own variables later.

Albertus
  • 911
  • 2
  • 10
  • 19
0

Check this post Programmatically save OpenXml document as previous version (Word 2007)

You'll have to modify your open xml power tools code.

This worked for me.

Hope this helps.

Community
  • 1
  • 1
Mohamed Alikhan
  • 1,315
  • 11
  • 14
0

Apparently, superfluous namespace declarations in the root element are removed with NormalizeXml = true but the associated prefixes that are mentioned in the mc:Ignorable attribute are not.

I use this to recursively inspect and fix all OpenXmlParts in the document:

private static void FixIgnorableAttributes(OpenXmlPartContainer container)
{
    container.Parts.Select(idPartPair => idPartPair.OpenXmlPart).ToList().ForEach(part =>
    {
        var ignorableAttribute = part.RootElement?.MCAttributes?.Ignorable;
        if (ignorableAttribute != null && ignorableAttribute.HasValue)
        {
            var root = part.GetXDocument().Root;

            ignorableAttribute.Value =
                string.Join(" ", ignorableAttribute.Value.Split(" ", StringSplitOptions.RemoveEmptyEntries).
                    Where(prefix => root.GetNamespaceOfPrefix(prefix) != null));
        }

        // Recursively fix descendant parts
        FixIgnorableAttributes(container: part);
    });
}

Usage:

using (WordprocessingDocument wordDocument = WordprocessingDocument.Open(pathOrStream, true))
{
    MarkupSimplifier.SimplifyMarkup(wordDocument, new SimplifyMarkupSettings { NormalizeXml = true });

    // Fix ignorables attributes
    FixIgnorableAttributes(wordDocument);
}
wensveen
  • 783
  • 10
  • 20