Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
//
// Pleast note that this code should be used as example code only, it is not properly tested.
//
public class DeploymentActionImportTaxonomy : DeploymentAction<bool>
{
public enum ImportTaxonomyMode
{
DeleteAndRecreate,
OnlyAddNew
}
public DeploymentActionImportTaxonomy(ClientContext context, string termGroupName, string csvFolderPath, ImportTaxonomyMode mode, bool verbose)
: base(context, "Importing taxonomy", verbose)
{
this.TermGroupName = termGroupName;
this.CsvFolderPath = csvFolderPath;
this.Mode = mode;
}
protected string TermGroupName { get; set; }
protected string CsvFolderPath { get; set; }
protected ImportTaxonomyMode Mode { get; set; }
protected override bool Action()
{
// Get the xml files to import
string[] filePaths = null;
try
{
filePaths = Directory.GetFiles(this.CsvFolderPath, "*.csv");
}
catch (Exception ex)
{
this.Print(string.Format("Failed to read from folder '{0}'. {1}", this.CsvFolderPath, ex.Message));
throw ex;
}
if(filePaths == null || !filePaths.Any())
{
// Nothing to import
this.Print("No csv files found to import in folder: " + this.CsvFolderPath);
return false;
}
// Get the term group into which we are importing
var taxonomySession = TaxonomySession.GetTaxonomySession(this.Context);
var termStore = taxonomySession.GetDefaultSiteCollectionTermStore();
var termGroup = termStore.GetSiteCollectionGroup(this.Context.Site, true);
termGroup.Name = this.TermGroupName;
this.Context.Load(termGroup);
this.Context.ExecuteQuery();
// Import each xml file
foreach(var filePath in filePaths)
{
string filename = filePath.Split('\\', '/').Last();
this.Print("");
this.Print("Importing taxonomy from: " + filename);
// Read file to string
string[] csvLines = null;
try
{
csvLines = System.IO.File.ReadAllLines(filePath);
}
catch (Exception ex)
{
this.Print("Failed to read from file. " + ex.Message);
break;
}
// Import the content
if (csvLines == null || csvLines.Length < 2)
{
this.Print("Nothing to import. The header line plus at least a single content line is required.");
}
else if (string.IsNullOrEmpty(csvLines.First()) || !csvLines.First().StartsWith(Constants.Taxonomy.CsvImportFirstLine))
{
this.Print("CSV is badly formed. First line should be: " + Constants.Taxonomy.CsvImportFirstLine);
}
else
{
// Import the lines (skipping the header line)
TermSet currentTermSet = null;
for (int i = 1; i < csvLines.Length; i++)
{
var csvLine = csvLines[i];
ImportCsvLine(termGroup, ref currentTermSet, csvLine);
}
}
}
return true;
}
private void ImportCsvLine(TermGroup termGroup, ref TermSet currentTermSet, string csvLineString)
{
if (string.IsNullOrEmpty(csvLineString))
{
this.Print("Encountered an empty content line");
}
else
{
var csvLineStringArray = GenericUtil.CsvSplit(csvLineString);
if (csvLineStringArray.Length < 12)
{
this.Print("A content line must contain at least 12 parts. e.g. " + Constants.Taxonomy.CsvImportFirstLine);
}
else
{
var csvLine = new TaxonomyImportCsvLine(csvLineStringArray);
currentTermSet = GetCurrentTermSet(termGroup, currentTermSet, csvLine);
Term term = GetOrCreateTerm(currentTermSet, csvLine, null, 1);
}
}
}
private Term GetOrCreateTerm(TermSet currentTermSet, TaxonomyImportCsvLine csvLine, Term parentTerm, uint termLevel)
{
string termName = csvLine.GetTermName(termLevel);
if (!string.IsNullOrEmpty(termName))
{
Term term = null;
if (parentTerm == null)
{
term = currentTermSet.Terms.TryGetTerm(termName);
}
else
{
term = parentTerm.Terms.TryGetTerm(termName);
}
if (term == null)
{
this.Print("Creating term: " + termName);
if (parentTerm == null)
{
term = currentTermSet.CreateTerm(termName, (int)csvLine.LCID, Guid.NewGuid());
}
else
{
term = parentTerm.CreateTerm(termName, (int)csvLine.LCID, Guid.NewGuid());
}
term.SetDescription(csvLine.TermDescription, (int)csvLine.LCID);
this.Context.Load(term);
try
{
this.Context.ExecuteQuery();
}
catch (ServerException ex)
{
//if(ex.ServerErrorTypeName == TaxonomyOperationException)
this.Print("Failed to create term: " + termName + ". " + ex.Message);
return null;
}
}
// Recursive call to next level
term = GetOrCreateTerm(currentTermSet, csvLine, term, (termLevel + 1));
return term;
}
else
{
return parentTerm;
}
}
private TermSet GetCurrentTermSet(TermGroup termGroup, TermSet currentTermSet, TaxonomyImportCsvLine csvLine)
{
if (currentTermSet != null)
{
bool usingPreviousTermSet = csvLine.AssignTermSetNameIfNullOrEmpty(currentTermSet.Name);
if (!usingPreviousTermSet)
{
// Get or create term set
currentTermSet = GetOrCreateTermSet(termGroup, csvLine);
}
else
{
// Do nothing, continue using the current term set
}
}
else
{
if (string.IsNullOrEmpty(csvLine.TermSetName))
{
this.Print("Term set has not been defined");
}
else
{
// Get or create term set
currentTermSet = GetOrCreateTermSet(termGroup, csvLine);
}
}
return currentTermSet;
}
private TermSet GetOrCreateTermSet(TermGroup termGroup, TaxonomyImportCsvLine csvLine)
{
TermSet termSet = termGroup.TermSets.TryGetTermSet(csvLine.TermSetName);
if (termSet != null && this.Mode == ImportTaxonomyMode.DeleteAndRecreate)
{
this.Print("Deleting existing term set: " + termSet.Name);
termSet.DeleteObject();
this.Context.Load(termSet);
this.Context.ExecuteQuery();
termSet = null;
}
if(termSet == null)
{
this.Print("Creating term set: " + csvLine.TermSetName);
termSet = termGroup.CreateTermSet(csvLine.TermSetName, Guid.NewGuid(), (int)csvLine.LCID);
termSet.Description = csvLine.TermSetDescription;
this.Context.Load(termSet);
this.Context.ExecuteQuery();
}
return termSet;
}
public class TaxonomyImportCsvLine
{
public TaxonomyImportCsvLine(string[] properties)
{
this.TermSetName = properties[0];
this.TermSetDescription = properties[1];
this.AvailableForTagging = properties[3];
this.TermDescription = properties[4];
this.TermNames = new string[7];
this.TermNames[0] = properties[5];
this.TermNames[1] = properties[6];
this.TermNames[2] = properties[7];
this.TermNames[3] = properties[8];
this.TermNames[4] = properties[9];
this.TermNames[5] = properties[10];
this.TermNames[6] = properties[11];
uint lcid;
if (uint.TryParse(properties[2], out lcid))
{
this.LCID = lcid;
}
else
{
this.LCID = Constants.Locales.Lcid.English_USA;
}
}
public string TermSetName { get; private set; }
public string TermSetDescription { get; private set; }
public uint LCID { get; private set; }
public string AvailableForTagging { get; private set; }
public string TermDescription { get; private set; }
private string[] TermNames { get; set; }
public bool AssignTermSetNameIfNullOrEmpty(string previousTermSetName)
{
if (string.IsNullOrEmpty(this.TermSetName))
{
this.TermSetName = previousTermSetName;
return true;
}
else
{
return false;
}
}
public string GetTermName(uint level)
{
if(level < 1 || level > 7)
{
throw new Exception("Can only get terms of level 1 through to 7");
}
var termNameAsProvided = this.TermNames[level - 1];
var cleanTermName = Regex.Replace(termNameAsProvided, "[^a-zA-Z0-9_ -]+", string.Empty);
return termNameAsProvided;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment