Move , Merge and Rename operations on Managed Metadata Term using powershell

Managed metadata is a hierarchical collection of centrally managed terms that you can define and then use as attributes for items in Microsoft SharePoint Server 2010. There may be scenario when you need to move terms in hierarchy or merger terms or may need to rename the term. All the operations mentioned can be easily done manually using Out of Box feature. Consider a scenario where you need to move say 50 terms or say need to perform merge operation on large number of terms, in this case doing these operation manually would take time.

To perform these operations in bulk, we can write powershell script and to make things generic and configurable, we can use source of script be xml file.In the sample code below, I will use xml as source of input to perform these operations. Structure of these xmls can be modified based on need however while making changes in xml we also need to make change in powershell to consider this structure change.

For Merge -

<Root>
<Merge> 
 <Term srcName ="T2" destName="T1"></Term>  
</Merge>
</Root>

For merging we can define the xml in format mentioned above (I am assuming there is only one term wih any name, if not then we need to take guid of term)

sample code to merge term -

$taxonomySession = Get-SPTaxonomySession -Site "SiteURL"

$termStore = $taxonomySession.TermStores["Your Managed Metadata Service Name"]
   $group = $termStore.Groups["Your Group Name"]
   if($group -eq $null)
    {
        return
    }
      
  
                                              
    $termSet = $group.TermSets | Where-Object { $_.Name -eq $termSetName }
               
    if($termSet -eq $null)
    {          
       return           
    }
      
    $movexml = [xml](Get-Content Merge.xml)            
   
    if($movexml.Root.ChildNodes.Count -gt 0) {
                  
        for($i = 0; $i -lt $movexml.Root.ChildNodes.Count; $i++) {            
                                    
            $OldTermName = $movexml.Root.ChildNodes.Item($i).Term.GetAttribute("srcName")
            $newTermName = $movexml.Root.ChildNodes.Item($i).Term.GetAttribute("destName")            
            
                       
            $Oldterm = $termSet.GetAllTerms() | Where-Object { $_.Name -eq $OldTermName }            
            $newterm = $termSet.GetAllTerms() | Where-Object { $_.Name -eq $newTermName }             
             
                      
            if($Oldterm -eq $null)
            {
                    Write-Output "Source Term is null"
            }
            elseif($newterm -eq $null)
            {
                Write-Output "Destination Term is null"
            }          
            else
            {
                    $Oldterm.Merge($newTerm)

            }
        }
     }
       
  
   $termStore.CommitAll();

 

For rename term-

<Root>
<Rename> 
 <Term oldName ="T1" newName="Term1"></Term>  
</Rename>
</Root>

Powershell -

$movexml = [xml](Get-Content Rename.xml)            
   
    if($movexml.Root.ChildNodes.Count -gt 0) {
                
        for($i = 0; $i -lt $movexml.Root.ChildNodes.Count; $i++) {            
                                    
            $OldTermName = $movexml.Root.ChildNodes.Item($i).Term.GetAttribute("oldName")
            $newTermName = $movexml.Root.ChildNodes.Item($i).Term.GetAttribute("newName")                                                   
            
            $term = $termSet.GetAllTerms() | Where-Object { $_.Name -eq $OldTermName }             
                                  
            if($term -eq $null)
            {
                    Write-Output "Source Term is null"
            }           
            else
            {
                    $term.Name = $newTermName

            }
        }
    }

 

Move Xml -

<Root>
<Move>
 <Source>
  <Term name ="T4">
  </Term>
 </Source>
 <Destination>
  <Term name="T1"> 
  </Term>
 </Destination>
</Move>
</Root>

Move powershell -

 

function MoveTerm
{
param($sourceTerm, $destTerm, $DestTermNode)

     if($DestTermNode.ChildNodes.Count -gt 0) {                   
            $childdestTermName = $DestTermNode.Term.GetAttribute("name")
            $childdestTermNode = $DestTermNode.Term
                      
            $childestTerm = $destTerm.Terms | Where-Object { $_.Name -eq $childdestTermName } 
                     
            MoveTerm $sourceTerm $childestTerm $childdestTermNode       
    }
    else
    {
              $sourceTerm.Move($destTerm)
    }                    
}

 

$movexml = [xml](Get-Content Move.xml)            
   
    if($movexml.Root.ChildNodes.Count -gt 0) {
    
        Write-OutPut "Move process Begin"
    
        for($i = 0; $i -lt $movexml.Root.ChildNodes.Count; $i++) {            
                                    
            $sourceTermName = $movexml.Root.ChildNodes.Item($i).Source.Term.GetAttribute("name")
            $destTermName = $movexml.Root.ChildNodes.Item($i).Destination.Term.GetAttribute("name")
            $DestTermNode = $movexml.Root.ChildNodes.Item($i).Destination.Term                        
            
            $sourceTerm = $termSet.Terms | Where-Object { $_.Name -eq $sourceTermName }
            $destTerm = $termSet.Terms | Where-Object { $_.Name -eq $destTermName }  
             
           if($sourceTerm -eq $null)
            {
                Write-Output "Source Term is null"
            }
            elseif($destTerm -eq $null)
            {
                Write-Output "Destination Term is null"
            }
            else
            {
                MoveTerm $sourceTerm $destTerm $DestTermNode
            }
        }
       
        Write-OutPut "Move process End"
    }