Thursday 5 June 2014

SharePoint 2010 - Export and import global navigation

I was working on a script to import and export Global navigation including the navigation settings for SharePoint sites.
Here’s the full script.

The first script exports the global navigation settings to the GlobalNavigationSettings.xml file and the navigation nodes with the hierarchy to the GlobalNavigationNodes.xml file

param([string]$siteUrl, [string]$exportPath = 'C:\Temp') 
$ErrorActionPreference = 'Stop'

If ((Get-PsSnapin |?{$_.Name -eq "Microsoft.SharePoint.PowerShell"})-eq $null)
{
      Add-PsSnapin Microsoft.SharePoint.PowerShell - ErrorAction SilentlyContinue | Out-Null
}

function Export-GlobalNavigation-Settings
{
      param([Microsoft.SharePoint.Publishing.PublishingWeb]$publishingWeb, [string]$exportPath)
      if([System.IO.Directory]::Exists($exportPath-ne $true)
      {
            Write-Error "Export path " $exportPath " is not valid. Make sure that the directory exists"
      }
      $fileName = [System.IO.Path]::Combine($exportPath"GlobalNavigationSettings.xml")
      Write-Host "Exporting global navigation settings to " $fileName
      ($publishingWeb.Navigation | ConvertTo-Xml).Save($fileName)
      Write-Host -ForegroundColor Green "Successfully exported global navigation settings.."
}

function Add-To-XmlDocument
{
      param([Xml.XmlNode]$xnode, [Microsoft.SharePoint.Navigation.SPNavigationNodeCollection$nodes, [int$level)  
      foreach($node in $nodes)
      {
            Write-Host -ForegroundColor Blue "Adding new navigation node" $node.Title
            [Xml.XmlNode$navigationNodeElement = $siteNavigationDoc.CreateElement("NavigationNode")
            [System.Xml.XmlAttribute$titleAttribute = $siteNavigationDoc.CreateAttribute("title")
            $titleAttribute.Value = $node.Title
            [System.Xml.XmlAttribute$urlAttribute = $siteNavigationDoc.CreateAttribute("url")
            $urlAttribute.Value = $node.Url
            [System.Xml.XmlAttribute$isVisibleAttribute = $siteNavigationDoc.CreateAttribute("isVisible")
            $isVisibleAttribute.Value = [string]$node.IsVisible
            [System.Xml.XmlAttribute$idAttribute = $siteNavigationDoc.CreateAttribute("id")
            $idAttribute.Value = [string]$node.Id
            [System.Xml.XmlAttribute$levelAttribute = $siteNavigationDoc.CreateAttribute("level")
            $levelAttribute.Value = [string]$level
            $navigationNodeElement.Attributes.Append($titleAttribute)
            $navigationNodeElement.Attributes.Append($urlAttribute)
            $navigationNodeElement.Attributes.Append($isVisibleAttribute)
            $navigationNodeElement.Attributes.Append($idAttribute)
            $navigationNodeElement.Attributes.Append($levelAttribute)
           
            if($node.Properties.Count -gt 0)
            {          
                  foreach($property in $node.Properties.GetEnumerator())
                  {
                        [Xml.XmlNode$propertyNode = $siteNavigationDoc.CreateElement("Property")
                        [Xml.XmlAttribute$keyAttribute = $siteNavigationDoc.CreateAttribute("key")
                        $keyAttribute.Value = [string]$property.Key
                        [Xml.XmlAttribute$valueAttribute = $siteNavigationDoc.CreateAttribute("value")
                        $valueAttribute.Value = [string]$property.Value
                        $propertyNode.Attributes.Append($keyAttribute)
                        $propertyNode.Attributes.Append($valueAttribute)
                        $navigationNodeElement.AppendChild($propertyNode)
                  }
            }
           
            $xnode.AppendChild($navigationNodeElement)
           
            Write-Host -ForegroundColor Green "Successfully added new navigation node" $node.Title
            if ($node.Children.Count -gt 0)
        {
                  $newLevel = $level + 1
            Add-To-XmlDocument $navigationNodeElement $node.Children $newLevel
        }                          
      }
}

function Export-GlobalNavigation-Nodes
{
      param([Microsoft.SharePoint.Publishing.PublishingWeb]$publishingWeb, [string]$exportPath)
      if([System.IO.Directory]::Exists($exportPath-ne $true)
      {
            Write-Error "Export path " $exportPath " is not valid. Make sure that the directory exists"
      }
      $fileName = [System.IO.Path]::Combine($exportPath"GlobalNavigationNodes.xml")
      Write-Host "Exporting global navigation settings to " $fileName
     
    [System.Xml.XmlNode$declarationNode = $siteNavigationDoc.CreateXmlDeclaration("1.0""UTF-8"$null)
    $siteNavigationDoc.AppendChild($declarationNode)

    [System.Xml.XmlNode$globalNavigationNode = $siteNavigationDoc.CreateElement("NavigationNodes")
    $siteNavigationDoc.AppendChild($globalNavigationNode)
     
      Add-To-XmlDocument $globalNavigationNode $publishingWeb.Navigation.GlobalNavigationNodes $nodeLevel
      $siteNavigationDoc.Save($fileName)
      Write-Host -ForegroundColor Green "Successfully exported global navigation settings.."
}


$site = Get-SPSite $siteUrl
$rootWeb = $site.RootWeb
$pubWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($rootWeb)
$nodeLevel = 1
Export-GlobalNavigation-Settings $pubWeb $exportPath

[System.Xml.XmlDocument$siteNavigationDoc = New-Object System.XML.XMLDocument    
Export-GlobalNavigation-Nodes $pubWeb $exportPath

The script creates two xml files, one with the navigation settings and one with the node hierarchy.




The second script is used to import the settings from the GlobalNavigationSettings.xml file and create navigation nodes from the GlobalNavigationNodes.xml file

param([string]$siteUrl, [string]$exportPath = 'C:\Temp')
$ErrorActionPreference = 'Stop'

If ((Get-PsSnapin |?{$_.Name -eq "Microsoft.SharePoint.PowerShell"})-eq $null)
{
      Add-PsSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue | Out-Null
}

function Import-GlobalNavigation-Settings
{
      param([Microsoft.SharePoint.Publishing.PublishingWeb]$publishingWeb, [string]$exportPath)
      if([System.IO.Directory]::Exists($exportPath-ne $true)
      {
            Write-Error "Export path " $exportPath " is not valid. Make sure that the directory exists"
      }
      $fileName = [System.IO.Path]::Combine($exportPath"GlobalNavigationSettings.xml")
      if([System.IO.File]::Exists($fileName-ne $true)
      {
            Write-Error "Unable to find site navigation settings file " $fileName
      }
      [xml]$settings = Get-Content $fileName
      $root = $settings.DocumentElement  
     
      Write-Host "Updating global navigation settings"
      Write-Host $root.SelectSingleNode('descendant::Object/Property[@Name="InheritGlobal"]').'#text'
      $var = [System.Convert]::ToBoolean($root.SelectSingleNode('descendant::Object/Property[@Name="GlobalIncludeSubSites"]').'#text')
      Write-Host $var
     
      $publishingWeb.Navigation.InheritGlobal = [System.Convert]::ToBoolean($root.SelectSingleNode('descendant::Object/Property[@Name="InheritGlobal"]').'#text')
      $publishingWeb.Navigation.GlobalIncludeSubSites = [System.Convert]::ToBoolean($root.SelectSingleNode('descendant::Object/Property[@Name="GlobalIncludeSubSites"]').'#text')
      $publishingWeb.Navigation.GlobalIncludePages = [System.Convert]::ToBoolean($root.SelectSingleNode('descendant::Object/Property[@Name="GlobalIncludePages"]').'#text')
      $publishingWeb.Navigation.GlobalDynamicChildLimit = [int]$root.SelectSingleNode('descendant::Object/Property[@Name="GlobalDynamicChildLimit"]').'#text'

      Write-Host "Updating current navigation settings"
      $publishingWeb.Navigation.InheritCurrent = [System.Convert]::ToBoolean($root.SelectSingleNode('descendant::Object/Property[@Name="InheritCurrent"]').'#text')
      $publishingWeb.Navigation.ShowSiblings = [System.Convert]::ToBoolean($root.SelectSingleNode('descendant::Object/Property[@Name="ShowSiblings"]').'#text')
      $publishingWeb.Navigation.CurrentIncludeSubSites = [System.Convert]::ToBoolean($root.SelectSingleNode('descendant::Object/Property[@Name="CurrentIncludeSubSites"]').'#text')
      $publishingWeb.Navigation.CurrentIncludePages = [System.Convert]::ToBoolean($root.SelectSingleNode('descendant::Object/Property[@Name="CurrentIncludePages"]').'#text')
      $publishingWeb.Navigation.CurrentDynamicChildLimit = [int]$root.SelectSingleNode('descendant::Object/Property[@Name="CurrentDynamicChildLimit"]').'#text'

      Write-Host "Updating rootweb navigation sorting settings"
      $publishingWeb.Navigation.OrderingMethod = [Microsoft.SharePoint.Publishing.OrderingMethod]$root.SelectSingleNode('descendant::Object/Property[@Name="OrderingMethod"]').'#text'
      $publishingWeb.Navigation.AutomaticSortingMethod = [Microsoft.SharePoint.Publishing.AutomaticSortingMethod]$root.SelectSingleNode('descendant::Object/Property[@Name="AutomaticSortingMethod"]').'#text'
      $publishingWeb.Navigation.SortAscending = [System.Convert]::ToBoolean($root.SelectSingleNode('descendant::Object/Property[@Name="SortAscending"]').'#text')

      #Update the Publishing Web Navigation Settings
      $publishingWeb.Update()
      Write-Host -ForegroundColor Green "Successfully imported global navigation settings.."
}


function Populate-NavigationNodes
{
      param ([Microsoft.SharePoint.Navigation.SPNavigationNodeCollection$nodes, [Xml.XmlNodeList$xNodes, [int$level)
      $level = $level + 1;
      foreach($xNode in $xNodes)
      {
            $title = $xNode.Title
            $url = $xNode.Url
            $isVisible =[Boolean]$xNode.IsVisible    
            $CreateNavigationNodeMethod = [Microsoft.SharePoint.Publishing.Navigation.SPNavigationSiteMapNode]::CreateSPNavigationNode
                 
            $nodeTypePropertyElement = $xNode.SelectSingleNode('descendant::Property[@key="NodeType"]')
            $nodeType = [Microsoft.SharePoint.Publishing.NodeTypes]::AuthoredLinkPlain
            if($nodeTypePropertyElement -ne $null)
            {
                  $nodeType = [System.Enum]::Parse([Microsoft.SharePoint.Publishing.NodeTypes], $nodeTypePropertyElement.value)
            }
            Write-Host -ForegroundColor Blue "Creating navigation node " $title
            $spNavigationNode = $CreateNavigationNodeMethod.Invoke($title$url$nodeType$nodes)
            $spNavigationNode.IsVisible = $isVisible
            $spNavigationNode.Update()
            Write-Host -ForegroundColor Green "Successfully created navigation node " $title
           
            $xPath = 'descendant::NavigationNode[@level="' + [string]$level + '"]'
           
            $navigationNodeElements = $xNode.SelectNodes($xPath)
            if($navigationNodeElements.Count -gt 0)
            {
                  Populate-NavigationNodes $spNavigationNode.Children $navigationNodeElements $level
            }
      }
}

function Import-GlobalNavigation-Nodes
{
      param([Microsoft.SharePoint.Publishing.PublishingWeb]$publishingWeb, [string]$exportPath)
      if([System.IO.Directory]::Exists($exportPath-ne $true)
      {
            Write-Error "Export path " $exportPath " is not valid. Make sure that the directory exists"
      }
      $fileName = [System.IO.Path]::Combine($exportPath"GlobalNavigationNodes.xml")
      if([System.IO.File]::Exists($fileName-ne $true)
      {
            Write-Error "Unable to find site navigation nodes file " $fileName
      }
     
      Write-Host "Removing existing global navigation nodes"
      $sharePointGlobalNodes = @(1000, 1002, 1025)
      for($i = $publishingWeb.Navigation.GlobalNavigationNodes.Count-1; $i -ge 0; $i--)
      {
            $node = $publishingWeb.Navigation.GlobalNavigationNodes[$i]
            if(($sharePointGlobalNodes -contains $node.Id-ne $true)
            {
                  Write-Host -ForegroundColor Blue $node.Title
                  $node.Delete()
                  $node.Update
            }
      }    
      $publishingWeb.Update()
     
      [xml]$nodesContent = Get-Content $fileName
      $root = $nodesContent.DocumentElement
      $spNavigationNodeElements = $root.SelectNodes('descendant::NavigationNode[@level="1"]')
     
      Populate-NavigationNodes $publishingWeb.Navigation.GlobalNavigationNodes $spNavigationNodeElements 1
      $publishingWeb.Update()
}

$site = Get-SPSite $siteUrl
$rootWeb = $site.RootWeb
$pubWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($rootWeb)
Import-GlobalNavigation-Settings $pubWeb $exportPath
Import-GlobalNavigation-Nodes $pubWeb $exportPath