Tuesday 8 January 2013

Using Powershell to export a SharePoint Managed Metadata termset to xml


The problem

You have a termset in one environment and want to move the termset and the sites content to another environment.

SharePoint OTB does allow you to import a termset from a CSV file (which can be easily edited in Excel). However should you restore a content database; then import your termset using the OTB method none of the content items will have valid entries.

The reason for this is first managed metadata , data is sorted in a separate database away from the content database, secondly content items do not store the actual term; they store the terms GUID. When using to OTB method for importing the termset, SharePoint does not allow you to specify the GUID and creates a new GUID. The final part of this problem is the site collection itself has a copy of the termset, stored in a hidden list called  “TaxonomyHiddenList” should the managed metadata (MM) service go down. You need to tell SharePoint to update this list to get the latest terms.

The solution

One potential solution is to backup and restore the MM database, however this would change all termsets and you may wish to just import one. So the best solution I have come up with is to write a Powershell script which exports the termset to a XML file and a corresponding script to import it.

To Export

First of all add the SharePoint Shell into the script:

   1: Add-PSSnapin “Microsoft.SharePoint.Powershell” –ErrorAction SilentlyContinue




Then create a SharePoint Taxonomy session:




   1: $siteUrl = “http://mySharePointSite/”

   2: $session = new-object Microsoft.SharePoint.Taxonomy.TaxonomySession($siteUrl)




Next get the Termstore, Group and Termset, all whilst writing to a XML string variable:




   1: $termSetStoreDesc = “Managed Metadata Service”

   2: $groupDesc = “MyGroup”

   3: $termSetName = “MyTermSet”

   4:  

   5: $XML = “<?xml version=’1.0’ ?>

   6: $termStore = $session.TermStores[$termSetStoreDesc]

   7: $XML += “<TermStore Name=’” + $termStore.Name + “’ GUID=’” + $termStore.ID + “’>

   8:  

   9: $group = $termStore.Groups[$groupDesc] 

  10:  

  11: $XML += “<Group Name=’” + $group.Name + “’ GUID=’” + $group.ID + “’>

  12:  

  13: $termSet = $Group.TermSets[$termSetName]

  14:  

  15: $XML = “<TermSetGroup Name=’” + $termSet.Name + ‘” GUID-‘” + $termSet.ID + “’>




Then get the terms within that termset and loop round them writing to XML and get the term beneath them and do the same:




   1: $terms = $termSet.GetTerms(200) 

   2:  

   3: Foreach ($term in $terms)

   4: {

   5:  

   6: $XML += “<Term><Name>” + $term.Name + “</Name><GUID>” + $term.ID + “</GUID>

   7:  

   8: If ($term.TermsCount –gt 0)

   9: {

  10: $XML += <ChildTerms>

  11:  

  12:     Foreach ($childTerm in $Term.Terms)

  13:     {

  14:          XML += “<Term><Name>” + $childTerm.Name + “</Name><GUID>” + $childTerm.ID + “</GUID></Term>

  15:     }

  16:  $XML += </ChildTerms>

  17: }

  18: $XML += </Term>


       }



Finally close the open XML tags and save the file:



      $


   1: $XML += “</TermSet></TermSetGroup></TermStore>

   2: $saveLoc = “C:\myXML.xml”

   3: $XML | out-File –FilePath $saveLoc


Altogether (properly structured)





   1: Add-PSSnapin “Microsoft.SharePoint.Powershell” –ErrorAction 

   2: SilentlyContinue

   3:  

   4: #Variables start

   5: $siteUrl = “http://mySharePointSite/”

   6: $termSetStoreDesc = “Managed Metadata Service”

   7:  

   8: $groupDesc = “MyGroup”

   9:  

  10: $termSetName = “MyTermSet”

  11: $saveLoc = “C:\myXML.xml”

   2: $session = new-object Microsoft.SharePoint.Taxonomy.TaxonomySession($siteUrl)

  13: #Variables end

  14:  

  15:  

  16:  $XML = “<?xml version=’1.0’?>

  17:  

  18: $termStore = $session.TermStores[$termSetStoreDesc]

  19:  

  20: $XML += “<TermStore Name=’” + $termStore.Name + “’ GUID=’” + $termStore.ID + “’>

  21:  

  22: $group = $termStore.Groups[$groupDesc] 

  23:  

  24: $XML += “<Group Name=’” + $group.Name + “’ GUID=’” + $group.ID + “’>

  25:  

  26: $termSet = $group.TermSets[$termSetName]

  27:  

  28: $XML = “<TermSetGroup Name=’” + $termSet.Name + ‘” GUID-‘” + $termSet.ID + ’>

  29:  

  30: $terms = $termSet.GetTerms(200) 

  31:  

  32: Foreach ($term in $terms)

  33: {

  34: $XML += “<Term><Name>” + $term.Name + “</Name><GUID>” + $term.ID + “</GUID>

  35:  

  36:     If ($term.TermsCount –gt 0)

  37:     {

  38:     $XML += "<ChildTerms>

  39:         Foreach ($childTerm in $term.Terms)

  40:         {

  41:             XML += “<Term><Name>” + $childTerm.Name + “</Name><GUID>” + $childTerm.ID + “</GUID></Term>

  42:         }

  43:         $XML += </ChildTerms>

  44:     }

  45:     $XML += </Term>

  46:     }

  47:      

  48:     $XML += “</TermSet></TermSetGroup></TermStore>

  49:  

  50: $XML | out-File –FilePath $saveLoc




If all done correctly your  output XML will have the following structure:

   1: <xml version="1.0">

   2: <TermStore Name="ABC" GUID="xxxx-xxxx-xxxx-xxxx">

   3:     <TermSetGroup Name="DEF" GUID="xxxx-xxxx-xxxx-xxxx">

   4:         <TermSet Name="GHI" GUID="xxxx-xxxx-xxxx-xxxx">

   5:             <Term>

   6:             <GUID>xxxx-xxxx-xxxx-xxxx</GUID>

   7:             <Name>JKL</Name>

   8:             <Description>blah</Description>

   9:             <IsAvailableForTagging>False</IsAvailableForTagging>

  10:                 <ChildTerms>

  11:                     <ChildTerm>

  12:                     <GUID>xxxx-xxxx-xxxx-xxxx</GUID>

  13:                     <Name>JKL Child</Name>

  14:                     <Description>blah</Description>

  15:                     <IsAvailableForTagging>True</IsAvailableForTagging>

  16:                     </ChildTerm>

  17:                 </ChildTerms>

  18:             </Term>

  19:         </TermSet>

  20:     </TermSetGroup>

  21: </TermStore>


To import this term set see this

1 comment: