C# using OpenXML to replace CustomXml not working

后端 未结 1 1292
遇见更好的自我
遇见更好的自我 2021-01-25 17:37

The following is the code I\'m using to create a new word document from an existing document. What does work is that it successfully reads the template document (templateName)

相关标签:
1条回答
  • 2021-01-25 18:28

    First, we probably need some more information:

    1. Is the XML being generated the same as what is already in the document?
      (Does it have the same namespace, format, etc?)
    2. Is there a possibility that the content controls in the document
      simply aren't mapped?
    3. Can you verify the XML is being written to the document?
      (It can be present in the document, but not show because it's not mapped, or the mapping is broken because the XML is different.)

    You can inspect the XML stored in the document in a variety of ways:

    1. Open XML SDK Productivity Tool
    2. Open XML Package Editor for Visual Studio
    3. Greg Maxey's Content Control Tools (VBA .dotm)
    4. Word Content Control Toolkit

    I think rather than DeleteParts<CustomXmlPart>(mainPart.CustomXmlParts) you should selectively replace the part you are looking for. You can (should) use the xmlns of the root element to identify parts (or you can test for root element name if your part doesn't have an xmlns and you can't add one either).

    This code demonstrates how to build the XML with a root namespace (which means all children need to also have that namespace). You'll have to research how to specify namespaces via attributes (or implement IXmlSerializable):

    XDocument GetXDocument()
    {
        var xmlns = (XNamespace)"http://schemas.tempuri.org/product/v1/wordMetadata";
    
        var childElement =
            new XElement(xmlns + "childElement",
                this.ChildCollection.Select(x => x.GetXElement(xmlns, "grandChildElement")));
    
        var rValue = new XDocument(
            new XElement(xmlns + "root",
                childElement
            ));
    
        return rValue;
    }
    
    public XElement GetXElement(XNamespace xmlns, string elementName)
    {
        return new XElement(xmlns + elementName);
    }
    

    The code below will replace the XML part in the document that has the same namespace as the incoming XDocument.

    public static class WriteWord
    {
        public static MemoryStream BuildFile(string templatePath, XDocument xmlData)
        {
            MemoryStream rValue = null;
            byte[] fileBytes;
    
            fileBytes = File.ReadAllBytes(templatePath);
            rValue = BuildFile(fileBytes, xmlData);
    
            return rValue;
        }
    
        public static MemoryStream BuildFile(byte[] fileBytes, XDocument xmlData)
        {
            var rValue = new MemoryStream();
    
            var reader = xmlData.CreateReader();
            reader.MoveToContent();
            var xmlNamespace = reader.NamespaceURI; // "http://schemas.tempuri.org/product/v1/wordMetadata";
    
            rValue.Write(fileBytes, 0, fileBytes.Length);
    
            var openSettings = new OpenSettings()
            {
                AutoSave = true,
                //MarkupCompatibilityProcessSettings = 
                //    new MarkupCompatibilityProcessSettings(
                //        MarkupCompatibilityProcessMode.ProcessAllParts, 
                //        FileFormatVersions.Office2013)
            };
            using (WordprocessingDocument doc = WordprocessingDocument.Open(rValue, true, openSettings))
            {
                MainDocumentPart main = doc.MainDocumentPart;
    
                var mainPart = doc.MainDocumentPart;
                var xmlParts = mainPart.CustomXmlParts;
                var ourPart = (CustomXmlPart)null;
    
                foreach (var xmlPart in xmlParts)
                {
                    var exists = false;
                    using (XmlTextReader xReader = new XmlTextReader(xmlPart.GetStream(FileMode.Open, FileAccess.Read)))
                    {
                        xReader.MoveToContent();
                        exists = xReader.NamespaceURI.Equals(xmlNamespace);
                    }
    
                    if (exists)
                    {
                        ourPart = xmlPart;
                        break;
                    }
                }
    
                using (var xmlMS = new MemoryStream())
                {
                    xmlData.Save(xmlMS);
                    xmlMS.Position = 0;
                    ourPart.FeedData(xmlMS);
                }
    
            }
    
            rValue.Position = 0;
    
    
            return rValue;
    
        }
    }
    
    0 讨论(0)
提交回复
热议问题