簡體   English   中英

C#使用OpenXML替換CustomXml無法正常工作

[英]C# using OpenXML to replace CustomXml not working

以下是我用來根據現有文檔創建新Word文檔的代碼。 起作用的是它成功讀取了模板文檔(templateName),並且能夠從模型類創建'customXML'字符串。 但是不能正常工作的是customXML信息(地址,城市,州,郵政編碼等)沒有替換空標簽。

我從一個較舊的.NET Web應用程序中提取了此代碼,並在帶有OpenXml 2.5的MVC 4.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類(客戶)的任何信息。 我看到過類似的帖子,但解決方案不起作用。

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

  1. 生成的XML是否與文檔中已有的XML相同?
    (它具有相同的名稱空間,格式等嗎?)
  2. 內容是否有可能在文檔中控制
    根本沒有映射?
  3. 您可以驗證將XML寫入文檔嗎?
    (它可以存在於文檔中,但由於未映射而未顯示,或者由於XML不同而導致映射被破壞。)

您可以通過多種方式檢查存儲在文檔中的XML:

  1. 打開XML SDK生產力工具
  2. 打開Visual Studio的XML包編輯器
  3. Greg Maxey的內容控制工具(VBA .dotm)
  4. Word內容控制工具包

我認為,您應該有選擇地替換要查找的部分,而不是DeleteParts<CustomXmlPart>(mainPart.CustomXmlParts) 您可以(應該)使用root元素的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;

    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM