A thorough dive into what happens when a rendering is removed has revealed that there's is not much triggered at all in Sitecore (Not like when a rendering is added which fires a pipeline). In fact, Experience Editor just removes the rendering and then relies on someone hitting the Save Button to actually save the changes, which at that point is merely just saving the field data.
I agree with Marek's comment in your question that hooking into the item:saving event should give you a look at what you're trying to discover. I do not think that you're going to find a solution that prevents you from having to compare the XML structs of the before and after item.
That being said, I found some code in the
saveUI pipeline that looks to me, like it's attempting to do something similar to what you are trying to do.
saveUI Pipeline Approach
BTW this is a total stab in the dark, but I'm going to try and provide
When Sitecore save's an item, it executes the
<saveUI> pipeline. As part of the arguments, it takes version and language into account.
In this pipeline, one of the processors is ConvertLayoutField which takes a look at the layout field before and after, and does some stuff. Here is the
public void Process(SaveArgs args)
Assert.ArgumentNotNull((object) args, "args");
Assert.IsNotNull((object) args.Items, "args.Items");
foreach (SaveArgs.SaveItem saveItem in args.Items)
Item obj = Client.ContentDatabase.Items[saveItem.ID, saveItem.Language, saveItem.Version];
if (obj != null)
foreach (SaveArgs.SaveField field1 in saveItem.Fields)
Field field2 = obj.Fields[field1.ID];
if (!field2.IsBlobField && !(field2.Type != "layout"))
string xml1 = field2.Value;
string xml2 = field1.Value;
if (!(xml1 == xml2) && (!string.IsNullOrEmpty(xml1) || string.IsNullOrEmpty(xml2)) && (string.IsNullOrEmpty(xml1) || !string.IsNullOrEmpty(xml2)))
XmlDocument xmlDocument1 = XmlUtil.LoadXml(xml1);
XmlDocument xmlDocument2 = XmlUtil.LoadXml(xml2);
if (xmlDocument2 != null && xmlDocument1 != null && ConvertLayoutField.CompareNodes((XmlNode) xmlDocument2, (XmlNode) xmlDocument1))
field1.Value = xml1;
In this processor,
SaveArgs contain the Item being updated, and the fields that were updated. In the processor above, is an example on identifying the layout field(s).
xml1 is the field value before the save (coming from Item in the Content Database field2).
xml2 is the field value after the save (coming from the SaveArgs Field field1).
So, a thought would be to create your own processor for this pipeline and use
XmlDiff to compare and get the differences on the layout field, and then do whatever work you need to do.