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

C# 在word文档中编辑自定义XML部分有时会损坏文档,c#,zip,openxml,docx,openxml-sdk,C#,Zip,Openxml,Docx,Openxml Sdk,我们有一个在Word文档中存储一些自定义模板数据的系统。有时,更新此数据会导致Word抱怨文档已损坏。当这种情况发生时,如果我解压缩docx文件并将其内容与以前的版本进行比较,唯一的区别似乎是customXML\item.xml文件中的预期更改。如果我使用7zip重新压缩内容,它似乎工作正常(Word不再抱怨文档已损坏) (简化)代码: void CreateOrReplaceCustomXml(字符串文件名,MyCustomData) { 使用(var doc=WordProcessingDo

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

(简化)代码:

void CreateOrReplaceCustomXml(字符串文件名,MyCustomData)
{
使用(var doc=WordProcessingDocument.Open(filename,true))
{
var part=GetCustomXmlParts(doc).SingleOrDefault();
if(part==null)
{
part=doc.MainDocumentPart.AddCustomXmlPart(CustomXmlPartType.CustomXml);
}
var serializer=新的DataContractSerializer(typeof(MyCustomData));
使用(var stream=new MemoryStream())
{
serializer.WriteObject(流、数据);
stream.Seek(0,SeekOrigin.Begin);
第三部分:数据流;
}
}
}
IEnumerable GetCustomXmlParts(WordProcessingDocument文档)
{
返回doc.MainDocumentPart.CustomXmlParts
。其中(部分=>
{
使用(var stream=doc.Package.GePart(c.Uri.GetStream())
使用(var streamReader=新streamReader(stream))
{
返回streamReader.ReadToEnd().Contains(“Some.Namespace”);
}
});
}

有什么建议吗?

因为重新压缩有效,所以内容似乎格式良好

所以听起来zip进程有问题。因此,在7-Zip中打开损坏的docx,并记下“method”列中的值(尤其是customXML\item.xml)


将该值与工作docx进行比较-是相同还是不同?方法“Deflate”有效。

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

几点建议 A.尝试doc.Package.Flush();将数据写回自定义xml后。 B您可能必须删除所有自定义零件并添加新的自定义零件。我们正在使用下面的代码,它似乎工作得很好

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
                }
publicstaticvoidreplacecustomxml(wordprocessingdocumentmydoc,stringcustomxml)
{
MainDocumentPart mainPart=myDoc.MainDocumentPart;
mainPart.DeleteParts(mainPart.CustomXmlParts);
CustomXmlPart CustomXmlPart=mainPart.AddCustomXmlPart(CustomXmlPartType.CustomXml);
使用(StreamWriter ts=newstreamwriter(customXmlPart.GetStream()))
{
ts.Write(customXML);
t.Flush();
ts.Close();
}
}
公共静态内存流GetCustomXmlPart(MainDocumentPart mainPart)
{
foreach(mainPart.CustomXmlParts中的CustomXmlPart部分)
{
使用(XmlTextReader)=
新的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=新的MemoryStream(byteArray);
回流;
}
}
}
返回null;//结果;
}
使用(WordprocessingDocument myDoc=WordprocessingDocument.Open(ms,true))
{
StreamReader=新的StreamReader(memStream);
字符串FullXML=reader.ReadToEnd();
ReplaceCustomXML(myDoc,FullXML);
myDoc.Package.Flush();
//保存文件的代码
}

一样-一切都“放气”好,很好。那我就把重点放在你的C代码上。当更新使数据变短或变长,或者没有模式时,是否会出现问题?重新压缩前后的包装大小(以7-Zip格式报告)是否相同?这帮助我解决了问题,因此很高兴授予rep:)我的实际问题是将完成的word文档写入文件…是否可以发布复制样本?
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
                }