InsertDocument doesn't always update Image rId [Solved - Minor change]

Aug 22, 2013 at 9:55 AM
Edited Aug 22, 2013 at 12:12 PM
First off, thanks for this amazing library! Great to see that it has been updated recently :)

Using the recent 1.0.0.13 build, I was able to merge documents (using the InsertDocument method) containing images, which is great.

However, I noticed that it doesn't work for all images. It works great as long as an image is inside <w:drawing> but fails when an image is inside <w:pict>. Then the relationship id of the image remains the same as it was in the original document, while the relationship id in the document.xml.rels part does change - resulting in a document that can't be opened.

I found the cause for this particular problem. Inside the DocX class, the method merge_images contains the following code to update the relationship id of the image inside the document:
// Replace all instances of remote_Id in the local document with local_Id
var elems = remote_mainDoc.Descendants(XName.Get("blip", DocX.a.NamespaceName));
foreach (var elem in elems)
{
    XAttribute embed = elem.Attribute(XName.Get("embed", DocX.r.NamespaceName));
    if (embed != null && embed.Value == remote_Id)
    {
        embed.SetValue(new_Id);
    }
}
Which explains why images inside <w:pict> don't get updated since they are represented like this in xml:
<w:pict>
  <v:shapetype id="_x0000_t75" coordsize=...>
    <v:stroke joinstyle="miter" />
    <v:formulas>
      ...
    </v:formulas>
    <v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect" />
    <o:lock v:ext="edit" aspectratio="t" />
  </v:shapetype>
  <v:shape id="_x0000_s1026" type="#_x0000_t75" style=...>
    <v:imagedata r:id="rId7" o:title="Fail2" />
    <w10:wrap type="square" anchorx="margin" anchory="margin" />
  </v:shape>
</w:pict>
The solution I came up with:

First, I added the XNamespace "v" inside the Namespaces region of the DocX class:
static internal XNamespace v = "urn:schemas-microsoft-com:vml";
Then I copied and edited the above code that searches and replaces the rId for "blip"/"embed" and edited it to replace the rId for "imagedata"/"id" as well:
// Replace all instances of remote_Id in the local document with local_Id (for shapes as well)
var v_elems = remote_mainDoc.Descendants(XName.Get("imagedata", DocX.v.NamespaceName));
foreach (var elem in v_elems)
{
    XAttribute id = elem.Attribute(XName.Get("id", DocX.r.NamespaceName));
    if (id != null && id.Value == remote_Id)
    {
        id.SetValue(new_Id);
    }
}
Might not be the most efficient way of going about this but it gets the job done. Thought it might be useful to share.

EDIT: The code needs to be added wherever the "blip"/"embed" code is used. Otherwise when an image already exists, the rId wouldn't be updated.
Coordinator
Aug 22, 2013 at 12:32 PM
Hi Annika89,

are you interested in submitting a patch for this issue? You solution seems like a very reasonable one. I'm sure the community would benefit from its inclusion in the source tree.

If you convert the above into a patch on codeplex I will gladly include it to the project.

Thanks a million,
Cathal
Aug 22, 2013 at 1:57 PM
Hi Cathal,

I would love to help out so I would definitely be interested.. but I have to admit I don't know how to go about converting this into a patch.
Don't know if it matters that I'm using SharpDevelop instead of Visual Studio either?
Coordinator
Aug 22, 2013 at 3:03 PM

I've actually never submitted a patch myself. I use Visual Studio and the TFS (Team Foundation Server) addon.

I could make the edit myself, you have provided enough information but it would be better if you experimented with adding the patch yourself. This way the contribution would be associated with your codeplex I'd and the developer community can grow.

Aug 23, 2013 at 9:15 AM
Just managed to create a patch using SVN and will upload it momentarily. (Let me know if that doesn't work for you - I'll give it another go)
Developer
Aug 23, 2013 at 10:55 AM
@Annika89,

I've merged your patch into source code. Please verify it works as you designed it. Unfortunately I wasn't able to apply patch directly but it was fairly simple to copy / paste from it :-) Thanks again. I'm glad that Cathal motivated you to apply that patch to library.
Aug 23, 2013 at 12:16 PM
Just tested it and it works, thanks for applying the patch :-)
Too bad it couldn't be used directly but I'm glad it wasn't too much of a hassle for you to copy/paste it.
Developer
Aug 23, 2013 at 12:47 PM
Well it's not your fault. Clearly I don't know how to use the tools from Codeplex. It wasn't accepting my password via some tool they provided so I got tired of trying ;) Thanks again. You're welcome to submit more stuff :)