The first question you’re going to ask is.. why the heck would you do that?

  1. Part of me is a little bit of a perfectionist. We’re not quite launched yet, and I want the presentation details as clean as possible before we start.  A good foundation never hurt.
  2. Part of me is still a little queasy when it comes to the four-tier set of presentation details on items.  I’m not alone.
  3. This is likely to be more performant.  Even just a hair when you take into account some higher-traffic sites.  I realize it’s cached, but it has to get processed a first time.

With my nice list of three out of the way, let’s get to it.

Consider this Shared Rendering:

<r xmlns:p="p" xmlns:s="s" p:p="1">
	<d id="{FE5D7FDF-89C0-4D99-9AA3-B5FBD009C9F3}">
		<r uid="{A7B9D573-8ED5-4F71-B5EF-31EE6B92CE32}" 
			s:ds="{3DB66721-C5B5-4006-95E6-533C6E5864EC}" 
			s:par="" />
		<r uid="{7237D059-717C-4042-9C54-24B8705C119F}" 
			s:ds="{D0B682BD-09FF-4E7A-9666-6924BD215AA9}" 
			s:par="CSS Class=%7B3C13A088-C7D9-4B39-992C-EDFCEC87E0E3%7D" />
		<r uid="{2E0239CB-49CA-42D9-8DD0-3D4E18121FA5}" 
			s:ds="{A337274E-ED74-4ADA-BC67-83310F37C870}" 
			s:par="CSS Class" />
		<r uid="{37289AF1-24D7-48A6-932E-5156D8F0B143}" 
			s:ds="{B1AA856A-3DC4-4683-8D77-EE819EE9CB57}" 
			s:par="CSS Class" />
		<r uid="{2D9811DA-33C5-4EF3-BBD6-F21AFBB090D5}" 
			s:ds="{E97D3F93-E74F-40C2-A38E-024C3704E0A7}" 
			s:par="" />
		<r uid="{CFD7251D-830B-40D2-AF4B-CD6282D0223A}" 
			p:after="r[@uid='{2D9811DA-33C5-4EF3-BBD6-F21AFBB090D5}']" 
			s:ds="{17E49769-25AF-467A-92F2-5EBFA562C1D2}" 
			s:id="{DC1A6EA7-986A-4CC5-ABAF-4DE85F92D031}" 
			s:par="" 
			s:ph="main" />
		<r uid="{CD7B5DFE-FFFD-4204-90A3-BE9EE06F7703}" 
			p:after="r[@uid='{CFD7251D-830B-40D2-AF4B-CD6282D0223A}']" 
			s:ds="{AB85D1DE-801D-414B-BFB1-E0C16F433C8D}" 
			s:id="{DC1A6EA7-986A-4CC5-ABAF-4DE85F92D031}" 
			s:par="" 
			s:ph="main" />
		<r uid="{A9169EEF-BB52-4B76-9AF8-A7EAEE3D0DA9}">
			<p:d />
		</r>
		<r uid="{1E223314-45A7-4FC2-8F38-B379348DE433}" 
			p:after="r[@uid='{BBA08A67-552A-49F1-A73E-E7CD663E5430}']" 
			s:ds="{EB73D71C-E0B9-4CA3-AFD2-050D765DA5AB}" 
			s:id="{DC1A6EA7-986A-4CC5-ABAF-4DE85F92D031}" 
			s:par="" 
			s:ph="main" />
	</d>
</r>

That’s a lot of XML, so apologies for that.

Now take in this Final Rendering on the same item:

<r xmlns:p="p" xmlns:s="s" p:p="1">
	<d id="{FE5D7FDF-89C0-4D99-9AA3-B5FBD009C9F3}">
		<r uid="{CD7B5DFE-FFFD-4204-90A3-BE9EE06F7703}" 
			s:ds="{D6B73A39-EE5D-4239-BF2E-91A3A66F9F31}" />
	</d>
</r>

All that is doing is swapping out the DataSource. That means that in Final, someone changed the Datasource and that’s it.

How do we fix this, you’re wondering.  I came up with a small chunk of code here, which worked much better than I had predicted.  I think I actually said “Whoa, that’s it??” when it worked.

private void MergeLayouts(Item item)
{
	//Grab the field that contains the layout
	var layoutField = new LayoutField(item.Fields[Sitecore.FieldIDs.LayoutField]);

	//Grab the field that contains the final layout
	var finalLayoutField = new LayoutField(item.Fields[Sitecore.FieldIDs.FinalLayoutField]);

	if (layoutField == null)
		throw new Exception("Couldn't find layout on: {0}".FormatWith(item.Name));

	if (finalLayoutField == null)
		throw new Exception("Couldn't find final layout on: {0}".FormatWith(item.Name));

	//If we don't have a final layout delta, we're good!
	if (string.IsNullOrWhiteSpace(finalLayoutField.Value))
	{
		return;
	}

	var finalLayoutDefinition = LayoutDefinition.Parse(finalLayoutField.Value);

	using (new EditContext(item))
	{
		layoutField.Value = finalLayoutDefinition.ToXml();
		item.Fields["__Final Renderings"].Reset();
		item.Editing.AcceptChanges();
	}
}

Yeah, that’s it.  The beauty lies in the “Parse” method. It actually composites all the deltas and gives you a true “final” value that can be set back on the Shared Renderings.

Here’s the final result:

<r xmlns:p="p" xmlns:s="s" p:p="1">
	<d id="{FE5D7FDF-89C0-4D99-9AA3-B5FBD009C9F3}">
		<r uid="{A7B9D573-8ED5-4F71-B5EF-31EE6B92CE32}" 
			s:ds="{3DB66721-C5B5-4006-95E6-533C6E5864EC}" 
			s:par="" />
		<r uid="{7237D059-717C-4042-9C54-24B8705C119F}" 
			s:ds="{D0B682BD-09FF-4E7A-9666-6924BD215AA9}" 
			s:par="CSS Class=%7B3C13A088-C7D9-4B39-992C-EDFCEC87E0E3%7D" />
		<r uid="{2E0239CB-49CA-42D9-8DD0-3D4E18121FA5}" 
			s:ds="{A337274E-ED74-4ADA-BC67-83310F37C870}" 
			s:par="CSS Class" />
		<r uid="{37289AF1-24D7-48A6-932E-5156D8F0B143}" 
			s:ds="{B1AA856A-3DC4-4683-8D77-EE819EE9CB57}" 
			s:par="CSS Class" />
		<r uid="{2D9811DA-33C5-4EF3-BBD6-F21AFBB090D5}" 
			s:ds="{E97D3F93-E74F-40C2-A38E-024C3704E0A7}" 
			s:par="" />
		<r uid="{CFD7251D-830B-40D2-AF4B-CD6282D0223A}" 
			p:after="r[@uid='{2D9811DA-33C5-4EF3-BBD6-F21AFBB090D5}']" 
			s:ds="{17E49769-25AF-467A-92F2-5EBFA562C1D2}" 
			s:id="{DC1A6EA7-986A-4CC5-ABAF-4DE85F92D031}" 
			s:par="" 
			s:ph="main" />
		<r uid="{CD7B5DFE-FFFD-4204-90A3-BE9EE06F7703}" 
			p:after="r[@uid='{CFD7251D-830B-40D2-AF4B-CD6282D0223A}']" 
			s:ds="{D6B73A39-EE5D-4239-BF2E-91A3A66F9F31}" 
			s:id="{DC1A6EA7-986A-4CC5-ABAF-4DE85F92D031}" 
			s:par="" 
			s:ph="main" />
		<r uid="{A9169EEF-BB52-4B76-9AF8-A7EAEE3D0DA9}">
			<p:d />
		</r>
		<r uid="{1E223314-45A7-4FC2-8F38-B379348DE433}" 
			p:after="r[@uid='{BBA08A67-552A-49F1-A73E-E7CD663E5430}']" 
			s:ds="{EB73D71C-E0B9-4CA3-AFD2-050D765DA5AB}" 
			s:id="{DC1A6EA7-986A-4CC5-ABAF-4DE85F92D031}" 
			s:par="" 
			s:ph="main" />
	</d>
</r>

Note that the only line changed is the highlighted one. This really is a surgeon’s approach to merging things back down a level, and I hope this helps someone else out!