在word文档中编辑自定义XML部分有时会损坏文档
本文关键字:文档 损坏 XML word 编辑 自定义 | 更新日期: 2023-09-27 18:03:23
我们有一个在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");
}
});
}
有什么建议吗?
既然重新压缩工作,内容似乎是格式良好的。
所以听起来zip过程有问题。因此,在7-Zip中打开损坏的docx,并注意"method"列中的值(特别是对于customXML'item.xml)。
将该值与工作文档进行比较-它是相同还是不同?方法"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
}