C#使用OpenXML替换CustomXml不起作用

本文关键字:CustomXml 不起作用 替换 OpenXML 使用 | 更新日期: 2023-09-27 18:20:08

以下是我用来从现有文档创建新单词文档的代码。它成功地读取了模板文档(templateName),并且能够从模型类中创建"customXML"字符串。但不起作用的是customXML信息(地址、城市、州、邮政编码…)没有替换空标记。

我从一个旧的.NET web应用程序中提取了这段代码,并在MVC 4.5和OpenXml 2.5中使用它。旧版本的代码有效,但在MVC版本中无效。

    public void CreateDocument(Customer customer, string templateName, string documentPath)
    {
        // Need to create an in memory resizable byte array for loading the county template
        byte[] byteArray = File.ReadAllBytes(templateName);
        using (MemoryStream mem = new MemoryStream())
        {
            mem.Write(byteArray, 0, (int)byteArray.Length);
            // Open the in memory Open XML document for processing 
            //using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(templateName, true))
            using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(mem, true))
            {
                // Build XML file from the Data Class that will be populated from data entered
                // into the Add Customer screen.  
                // THIS CODE WORKS - A VALID XML STRING IS CREATED
                string customXML = BuildCustomXmlPartFromDataClass(customer);
                // Replace Custom XML portion of Open XML Package document
                // THE mainPart.CustomXmlParts IS NOT NULL
                MainDocumentPart mainPart = wordDoc.MainDocumentPart;
                if (mainPart.CustomXmlParts != null)
                {
                    mainPart.DeleteParts<CustomXmlPart>(mainPart.CustomXmlParts);
                }
                CustomXmlPart customXmlPart = mainPart.AddCustomXmlPart(CustomXmlPartType.CustomXml);
                using (StreamWriter ts = new StreamWriter(customXmlPart.GetStream())) ts.Write(customXML);
            }
            // Save the in memory byte array to disk using a FileStream
            using (FileStream fileStream = new FileStream(documentPath, System.IO.FileMode.Create))
            {
                mem.WriteTo(fileStream);
            }
            // NEW DOCUMENT IS CREATED BUT IT DOES NOT CONTAIN ANY OF THE INFORMATION FROM THE MODEL CLASS
        }
    }
    protected string BuildCustomXmlPartFromDataClass(Customer customer)
    {
        // Serialize the Data Class to XML
        System.Xml.XmlDocument doc = new XmlDocument();
        System.Xml.Serialization.XmlSerializer serializer = 
            new System.Xml.Serialization.XmlSerializercustomer.GetType());
        System.IO.MemoryStream stream = new System.IO.MemoryStream();
        try
        {
            serializer.Serialize(stream, customer);
            stream.Position = 0;
            doc.Load(stream);
            return doc.InnerXml;
        }
        catch
        {
            throw;
        }
        finally
        {
            stream.Close();
            stream.Dispose();
        }
    }

没有错误,并且创建了一个新文档,但它不包含来自Model类(客户)的任何信息。我看到过类似的帖子,但解决方案不起作用。

C#使用OpenXML替换CustomXml不起作用

首先,我们可能需要更多信息:

  1. 生成的XML是否与文档中已有的内容相同
    (它有相同的名称空间、格式等吗?)
  2. 文档中的内容控件是否有可能
    根本没有映射
  3. 您能验证XML是否正在写入文档吗
    (它可能存在于文档中,但由于未映射而不显示,或者由于XML不同而导致映射中断。)

您可以通过多种方式检查文档中存储的XML:

  1. 开放式XML SDK生产力工具
  2. Visual Studio的开放式XML包编辑器
  3. Greg Maxey的内容控制工具(VBA.dotm)
  4. Word内容控制工具包

我认为你应该有选择地更换你正在寻找的零件,而不是DeleteParts<CustomXmlPart>(mainPart.CustomXmlParts)。您可以(应该)使用根元素的xmlns来识别部件(或者,如果您的部件没有xmlns,并且您也不能添加xmlns,则可以测试根元素名称)。

这段代码演示了如何使用根名称空间构建XML(这意味着所有子级也需要具有该名称空间)。您必须研究如何通过属性指定名称空间(或实现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);
}

下面的代码将替换文档中与传入XDocument具有相同名称空间的XML部分。

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;
    }
}