Create a gist now

Instantly share code, notes, and snippets.

Using LINQ to bulk extract Kentico's templates and documents/pages that use them
// Using Kentico site export, find all templates and associated Documents/pages, skip templates that are not used
// Uses LINQPad's C# Statements format
//Root directory where the unzipped Kentico export file sit (with Data subdirectory)
string exportDirPath = @"<UNZIPPED_FULL_SITE_EXPORT>\Data";
//XML files for documents and templates definitions
XDocument docSource = XDocument.Load(exportDirPath + @"\Documents\cms_document.xml.export");
XDocument templateSource = XDocument.Load(exportDirPath + @"\Objects\cms_pagetemplate.xml.export");
XDocument siteTemplateSource = XDocument.Load(exportDirPath + @"\Site\cms_pagetemplate.xml.export");
//combine the template sources with the same shape
var allTemplates =
(from t1 in templateSource.XPathSelectElements("//NewDataSet/cms_pagetemplate") select t1)
(from t2 in siteTemplateSource.XPathSelectElements("//NewDataSet/cms_pagetemplate") select t2)
).OrderBy(t => t.Element("PageTemplateDisplayName").Value);
// join templates and documents on the template ID and group documents by the template
var usedTemplates =
template in allTemplates
doc in docSource.XPathSelectElements("//NewDataSet/*[DocumentPageTemplateID]") //use * is because actual entries have different names, use [condition] is because not every document has a template (could inherit from parent instead)
on template.Element("PageTemplateID").Value equals doc.Element("DocumentPageTemplateID").Value
into g //group by PageTemplateID
where g.Count() > 0 //only keep the groups where there are documents associated with templates
select new {
Template = template,
Docs = g
//Get the template category entries that are in the same files as templates, but with different element name
//Some templates categories show up in both files, but they seem to be identical and will collapse on Union
var allTemplateCategories =
(from tc1 in templateSource.XPathSelectElements("//NewDataSet/cms_pagetemplatecategory") select tc1)
(from tc2 in siteTemplateSource.XPathSelectElements("//NewDataSet/cms_pagetemplatecategory") select tc2)
// print (using LINQPad's Dump() method) each template, whether it is a master and the documents associated with that template
foreach (var entry in usedTemplates)
var template = entry.Template;
//Find the category this template belongs to, just in case they are misplaced
string templateCategory = allTemplateCategories.Single(
tc => (tc.Element("CategoryID").Value == template.Element("PageTemplateCategoryID").Value))
string templateInfo = String.Format("{0} (Category: '{1}'; Master: {2}) - {3} entries",
var docs =
(from doc in entry.Docs
select new {
Document = doc.Element("NodeAliasPath").Value,
Culture = doc.Element("DocumentCulture").Value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment