I'm trying to edit a XmlDocument
file contained in a Zip file:
var zip = new ZipArchive(myZipFileInMemoryStream, ZipArchiveMode.Update);
var entry = zip.GetEntry("filenameToEdit");
using (var st = entry.Open())
{
var xml = new XmlDocument();
xml.Load(st);
foreach (XmlElement el in xml.GetElementsByTagName("Relationship"))
{
if(el.HasAttribute("Target") && el.GetAttribute("Target").Contains(".dat")){
el.SetAttribute("Target", path);
}
}
xml.Save(st);
}
After executing this code the contained file is not changed. IF instead of xml.Save(st);
I write the xml to disk, I got the edited one.
Why is the edited file not written to the zip? How do I fix it?
I have then updated the code:
var tmp = new MemoryStream();
using (var zip = new ZipArchive(template, ZipArchiveMode.Read, true))
{
var entry = zip.GetEntry("xml");
using (var st = entry.Open())
{
var xml = new XmlDocument();
xml.Load(st);
foreach (XmlElement el in xml.GetElementsByTagName("Relationship"))
{
if (el.HasAttribute("Target") && el.GetAttribute("Target").Contains(".dat"))
{
el.SetAttribute("Target", path);
}
}
xml.Save(tmp);
}
}
using (var zip = new ZipArchive(template, ZipArchiveMode.Update, true))
{
var entry = zip.GetEntry("xml");
using (var st = entry.Open())
{
tmp.Position = 0;
tmp.CopyTo(st);
}
}
In this way the zip file is edited, but it works only if the length of the streams is equal. If tmp
is shorter the rest of the st
is still in the file...
I use this code to create a Zip InMemory (using the DotNetZip Library) :
MemoryStream saveStream = new MemoryStream();
ZipFile arrangeZipFile = new ZipFile();
arrangeZipFile.AddEntry("test.xml", "content...");
arrangeZipFile.Save(saveStream);
saveStream.Seek(0, SeekOrigin.Begin);
saveStream.Flush(); // might be useless, because it's in memory...
After that I have a valid Zip inside the MemoryStream. I'm not sure why I added the Flush() - I would guess this is redundant.
To edit an existing Zip you could read it in a MemoryStream and instead of creating "new ZipFile()" use "new ZipFile(byteArray...)".