在word文档中编辑自定义XML部分有时会破坏文档

时间:2014-05-15 08:27:15

标签: c# zip openxml docx openxml-sdk

我们有一个系统可以在Word文档中存储一些自定义模板数据。有时,更新此数据会导致Word抱怨文档已损坏。当发生这种情况时,如果我解压缩docx文件并将内容与先前版本进行比较,则唯一的区别似乎是customXML\item.xml文件中的预期更改。如果我使用7zip重新压缩内容,它似乎工作正常(Word不再抱怨文档已损坏)。

(简化)代码:

void CreateOrReplaceCustomXml(string filename, MyCustomData data)
{
    using (var doc = WordProcessingDocument.Open(filename, true))
    {
        var part = GetCustomXmlParts(doc).SingleOrDefault();
        if (part == null)
        {
            part = doc.MainDocumentPart.AddCustomXmlPart(CustomXmlPartType.CustomXml);
        }

        var serializer = new DataContractSerializer(typeof(MyCustomData));
        using (var stream = new MemoryStream())
        {
            serializer.WriteObject(stream, data);
            stream.Seek(0, SeekOrigin.Begin);
            part.FeedData(stream);
        }
    }
}

IEnumerable<CustomXmlPart> GetCustomXmlParts(WordProcessingDocument doc)
{
    return doc.MainDocumentPart.CustomXmlParts
        .Where(part =>
        {
            using (var stream = doc.Package.GePart(c.Uri).GetStream())
            using (var streamReader = new StreamReader(stream))
            {
                return streamReader.ReadToEnd().Contains("Some.Namespace");
            }
        });
}

有什么建议吗?

3 个答案:

答案 0 :(得分:1)

由于重新压缩工作,内容似乎很好。

所以听起来拉链过程有问题。因此,在7-Zip中打开损坏的docx,并注意&#34;方法&#34;中的值。列(特别是对于customXML \ item.xml)。

将该值与工作docx进行比较 - 它是相同还是不同?方法&#34;放气&#34;的工作原理。

答案 1 :(得分:0)

我遇到了同样的问题,原来这是由于编码。 序列化/反序列化时是否已指定相同的编码?

答案 2 :(得分:0)

一对建议 一个。试试doc.Package.Flush();将数据写回自定义xml后。 湾您可能必须删除所有自定义零件并添加新的自定义零件。我们使用以下代码,似乎工作正常。

public static void ReplaceCustomXML(WordprocessingDocument myDoc, string customXML)
    {

        MainDocumentPart mainPart = myDoc.MainDocumentPart;
        mainPart.DeleteParts<CustomXmlPart>(mainPart.CustomXmlParts);
        CustomXmlPart customXmlPart =     mainPart.AddCustomXmlPart(CustomXmlPartType.CustomXml);
        using (StreamWriter ts = new StreamWriter(customXmlPart.GetStream()))
        {
            ts.Write(customXML);
            ts.Flush();
            ts.Close();
        }
    }

public static MemoryStream GetCustomXmlPart(MainDocumentPart mainPart)
    {
        foreach (CustomXmlPart part in mainPart.CustomXmlParts)
        {
            using (XmlTextReader reader =
                new XmlTextReader(part.GetStream(FileMode.Open, FileAccess.Read)))
            {
                reader.MoveToContent();
                if (reader.Name.Equals("aaaa", StringComparison.OrdinalIgnoreCase))
                {
                    string str = reader.ReadOuterXml();
                    byte[] byteArray = Encoding.ASCII.GetBytes(str);
                    MemoryStream stream = new MemoryStream(byteArray);

                    return stream;
                }
            }
        }

        return null; //result;
    }

using (WordprocessingDocument myDoc = WordprocessingDocument.Open(ms, true))
                {
                    StreamReader reader = new StreamReader(memStream);
                    string FullXML = reader.ReadToEnd();
                    ReplaceCustomXML(myDoc, FullXML);

                    myDoc.Package.Flush();

                    //Code to save file
                }