Post-2-the pages- Publishing Sites structural navigation bulk export and import of navigation items hide or show


In the post https://blogs.msdn.microsoft.com/joerg_sinemus/2016/08/04/publishing-sites-structural-navigation-bulk-export-and-import-of-navigation-items-hide-or-show/ we talked about SubSite navigation items, but there are also pages that can be set to show or hide.

Working with the pages is a bit more tricky, because we need to do that with the context of the SubSite, therefore more information is needed when importing the settings later.

image

On the Site Collection we see the SubSites and the Pages living in the Pages library inside the SiteCol. We can set a page to being visible in current and global separately.

How it looks for pages in SubSites?

image

Here we can set a page to show or hide, but not differentiate it to current and/or global.

Part 1, the Export:

Put the text into Export-Pages.ps1

################################################################################################

# THIS CODE-SAMPLE IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED

# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR

# FITNESS FOR A PARTICULAR PURPOSE.

#

# This sample is not supported under any Microsoft standard support program or service.

# The script is provided AS IS without warranty of any kind. Microsoft further disclaims all

# implied warranties including, without limitation, any implied warranties of merchantability

# or of fitness for a particular purpose. The entire risk arising out of the use or performance

# of the sample and documentation remains with you. In no event shall Microsoft, its authors,

# or anyone else involved in the creation, production, or delivery of the script be liable for

# any damages whatsoever (including, without limitation, damages for loss of business profits,

# business interruption, loss of business information, or other pecuniary loss) arising out of

# the use of or inability to use the sample or documentation, even if Microsoft has been advised

# of the possibility of such damages.

################################################################################################

 

# This script may need to know the URL we want to start and the file to export the needed

Param(

  [Parameter(Mandatory=$True)]

  [string]$SiteColUrl,

  [Parameter(Mandatory=$True)]

  [string]$ExportFile

)

 

Write-Host -ForegroundColor White “This script exports structural navigation information regarding hide or show a navigation item”

Write-Host -ForegroundColor Yellow “From Site Collection : “ $SiteColUrl

Write-Host -ForegroundColor Yellow “Into the file        : “ $ExportFile

 

# Set the Site Collection

$SPSite = Get-SPSite -Identity $SiteColUrl

 

# Construct an out-array to use for data export

$OutArray = @()

 

# Go through each site in the Site Collection

foreach ($SPWeb in $SPSite.AllWebs)

{

    if ($SPWeb.IsRootWeb)

    {

        # Process the root web

        # Set the Publishing Web

        $SPPubWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($SPWeb)

        Write-Host -ForegroundColor Gray “Currently working on : “ -NoNewline

        $SPPubWeb.Web.Url

 

        #

        # To have it easier when importing, let us write the Information about the Site Collection

        # first into the XML; without breaking the Schema we need for the Pages

        #

 

        # Construct an object, that contains SiteUrl,…, Global and Current navigation true or false

        $myobj = “” | Select “SiteUrl”, “Uri”, “Title”, “UniqueId”, “Current”,“Global”

        # fill the object

        $myobj.SiteUrl = $SPPubWeb.Web.Url

        $myobj.Uri = $SPPubWeb.Web.Url

        $myobj.Title = $SPPubWeb.Web.Title

        $myobj.UniqueId = $SPPubWeb.Web.ID

        $myobj.Current = $SPPubWeb.IncludeInCurrentNavigation

        $myobj.Global = $SPPubWeb.IncludeInGlobalNavigation

 

        # Add the object to the out-array

        $OutArray += $myobj

 

        # Wipe the object just to be sure

        $myobj = $null

 

        # Now the Pages

        $PubPages = $SPPubWeb.GetPublishingPages()

 

        foreach($PubOnePage in $PubPages)

        {

            # Construct an object, that contains SiteUrl,…, Global and Current navigation true or false

            $myobj = “” | Select “SiteUrl”, “Uri”, “Title”, “UniqueId”, “Current”,“Global”

            # fill the object

            $myobj.SiteUrl = $PubOnePage.PublishingWeb.Web.Url

            $myobj.Uri = $PubOnePage.Uri

            $myobj.Title = $PubOnePage.Title

            $myobj.UniqueId = $PubOnePage.ListItem.UniqueId

            $myobj.Current = $PubOnePage.IncludeInCurrentNavigation

            $myobj.Global = $PubOnePage.IncludeInGlobalNavigation

 

            # Add the object to the out-array

            $OutArray += $myobj

 

            # Wipe the object just to be sure

            $myobj = $null

        }

        $SPPubWeb.Web.Dispose()

    }

 

else

        # Now all the SubSites first level

    {

        ## Not a Root-Site but also needs to get the publishing web object

        $SPPubWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($SPWeb)

        Write-Host -ForegroundColor Gray “Currently working on : “ -NoNewline

        $SPPubWeb.Web.Url

 

        # Here Pages

        $PubPages = $SPPubWeb.GetPublishingPages()

 

        foreach($PubOnePage in $PubPages)

        {

            # Construct an object, that contains SiteUrl,…, Global and Current navigation true or false

            $myobj = “” | Select “SiteUrl”, “Uri”, “Title”, “UniqueId”, “Current”,“Global”

            # fill the object

            $myobj.SiteUrl = $PubOnePage.PublishingWeb.Web.Url

            $myobj.Uri = $PubOnePage.Uri

            $myobj.Title = $PubOnePage.Title

            $myobj.UniqueId = $PubOnePage.ListItem.UniqueId

            $myobj.Current = $PubOnePage.IncludeInCurrentNavigation

            $myobj.Global = $PubOnePage.IncludeInGlobalNavigation

 

            # Add the object to the out-array

            $OutArray += $myobj

 

            # Wipe the object just to be sure

            $myobj = $null

        }

        $SPPubWeb.Web.Dispose()

    }

}

$SPSite.Dispose()

 

# Now we can write our stuff into a File:

# After the loop, export the array to CSV/XML etc.

$OutArray | Export-Clixml $ExportFile -NoClobber

 

Write-Host -ForegroundColor Green “We are done, please check the file : “ -NoNewline

$ExportFile

 

You can run from your SharePoint 2013 Management Shell similar to: C:\Users\Administrator.Contoso\Documents\Export-Pages.ps1 –SiteColUrl http://Contoso/Sites/Contoso-Pub –ExportFile “C:\Users\Administrator.Contoso\Documents\Export-Contoso-Pages.xml”

Part 2, the content of the XML file:

<Objs Version=1.1.0.1 xmlns=http://schemas.microsoft.com/powershell/2004/04>

  <Obj RefId=0>

    <TN RefId=0>

      <T>Selected.System.String</T>

      <T>System.Management.Automation.PSCustomObject</T>

      <T>System.Object</T>

    </TN>

    <MS>

      <S N=SiteUrl>http://contoso/sites/contoso-pub</S>

      <S N=Uri>http://contoso/sites/contoso-pub</S>

      <S N=Title>US-Contoso</S>

      <G N=UniqueId>04323ef6-d7a3-4e89-8238-262de18a0a49</G>

      <B N=Current>true</B>

      <B N=Global>true</B>

    </MS>

  </Obj>

  <Obj RefId=1>

    <TNRef RefId=0 />

    <MS>

      <S N=SiteUrl>http://contoso/sites/contoso-pub</S>

      <URI N=Uri>http://contoso/sites/contoso-pub/Pages/PageNotFoundError.aspx</URI>

      <S N=Title>Page not found</S>

      <G N=UniqueId>5e570dd6-bc37-471a-9388-3991c9d52f92</G>

      <B N=Current>false</B>

      <B N=Global>false</B>

    </MS>

  </Obj>

  <Obj RefId=2>

    <TNRef RefId=0 />

    <MS>

      <S N=SiteUrl>http://contoso/sites/contoso-pub</S>

      <URI N=Uri>http://contoso/sites/contoso-pub/Pages/default.aspx</URI>

      <S N=Title>Home</S>

      <G N=UniqueId>c9b07283-8be1-4740-8f76-b6423f6c1cd5</G>

      <B N=Current>true</B>

      <B N=Global>false</B>

    </MS>

  </Obj>

  <Obj RefId=3>

    <TNRef RefId=0 />

    <MS>

      <S N=SiteUrl>http://contoso/sites/contoso-pub</S>

      <URI N=Uri>http://contoso/sites/contoso-pub/Pages/EnterThisSite.aspx</URI>

      <S N=Title>Enter This Site</S>

      <G N=UniqueId>c0cae256-0145-4fb3-b230-f061bd5686f0</G>

      <B N=Current>true</B>

      <B N=Global>true</B>

    </MS>

  </Obj>

  <Obj RefId=4>

    <TNRef RefId=0 />

    <MS>

      <S N=SiteUrl>http://contoso/sites/contoso-pub/SecSubSite</S>

      <URI N=Uri>http://contoso/sites/contoso-pub/SecSubSite/Pages/default.aspx</URI>

      <S N=Title>Home</S>

      <G N=UniqueId>c801b67a-56ab-4f9f-ad78-2f2ef06ebb59</G>

      <B N=Current>true</B>

      <B N=Global>true</B>

    </MS>

  </Obj>

  <Obj RefId=5>

    <TNRef RefId=0 />

    <MS>

      <S N=SiteUrl>http://contoso/sites/contoso-pub/SecSubSite</S>

      <URI N=Uri>http://contoso/sites/contoso-pub/SecSubSite/Pages/MoreLandingPage.aspx</URI>

      <S N=Title>MoreLandingPage</S>

      <G N=UniqueId>c9c9c772-ca9b-490d-bd17-4f38f131070b</G>

      <B N=Current>false</B>

      <B N=Global>false</B>

    </MS>

  </Obj>

  <Obj RefId=6>

    <TNRef RefId=0 />

    <MS>

      <S N=SiteUrl>http://contoso/sites/contoso-pub/SubSite-First</S>

      <URI N=Uri>http://contoso/sites/contoso-pub/SubSite-First/Pages/default.aspx</URI>

      <S N=Title>Home</S>

      <G N=UniqueId>fa9645c0-095f-4403-baef-48cfac137450</G>

      <B N=Current>true</B>

      <B N=Global>true</B>

    </MS>

  </Obj>

  <Obj RefId=7>

    <TNRef RefId=0 />

    <MS>

      <S N=SiteUrl>http://contoso/sites/contoso-pub/SubSite-First</S>

      <URI N=Uri>http://contoso/sites/contoso-pub/SubSite-First/Pages/LandingPage.aspx</URI>

      <S N=Title>Landing Page on SubSite</S>

      <G N=UniqueId>05ef6cfb-3b27-4300-9a5b-47afa4b120e9</G>

      <B N=Current>false</B>

      <B N=Global>false</B>

    </MS>

  </Obj>

</Objs>

 

Part 3, edit the XML file:

In this example change false and true. Remember, for Pages in SubSites you may use only the Current property. You may also remove all unnecessary entries, it will also improve the performance when importing.

Please be careful with editing the file, the code does not contain syntax checks and more, it is just an example for the bulk change of navigation items, hide or show. Some information might not be important, because for the import we need the SiteCol Url, SubSite Url, UniqueId, Current and Global. The title should help to identify your SubSite. In any way you can pimp up the script to export much more or also more levels of SubSites.

Part 4, the Import:

Put the text into Import-Pages.ps1

################################################################################################

# THIS CODE-SAMPLE IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED

# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR

# FITNESS FOR A PARTICULAR PURPOSE.

#

# This sample is not supported under any Microsoft standard support program or service.

# The script is provided AS IS without warranty of any kind. Microsoft further disclaims all

# implied warranties including, without limitation, any implied warranties of merchantability

# or of fitness for a particular purpose. The entire risk arising out of the use or performance

# of the sample and documentation remains with you. In no event shall Microsoft, its authors,

# or anyone else involved in the creation, production, or delivery of the script be liable for

# any damages whatsoever (including, without limitation, damages for loss of business profits,

# business interruption, loss of business information, or other pecuniary loss) arising out of

# the use of or inability to use the sample or documentation, even if Microsoft has been advised

# of the possibility of such damages.

################################################################################################

 

# This script may need to know the the filename with all the information, created by Export-Pages.ps1

Param(

  [Parameter(Mandatory=$True)]

  [string]$ImportFile

)

 

Write-Host -ForegroundColor White “This script imports structural navigation settings regarding hide or show a navigation-pages item”

Write-Host -ForegroundColor Yellow “From the file : “ $ImportFile

 

# Import the content from the file into an Array.

$ImportArray = Import-Clixml $ImportFile

 

# How many Items are in the file?

Write-Host -ForegroundColor Gray “We found “ ($ImportArray.Count1) “Pages in the file”

 

# It makes no sense to use the first entry in the XML file, because

# that is just the information for the SiteCol 😉

 

$i = 1 # Set pointer to 1; 0 is the SiteCol information

 

Do ## let it run until the last item has been processed

{

    # Take the item out of the array

    $ImportItem = $ImportArray[$i]

 

    # We need an own object for each page and for performance reasons

    # we could check it later to optimize the new obejct creation.

    # Optimizing performance, feel free to pimp this script up

    $SPWeb = Get-SPWeb -Identity $ImportItem.SiteUrl

    $PuWeb = [Microsoft.SharePoint.Publishing.PublishingWeb]::GetPublishingWeb($SPWeb)

   

    #Write-Host -ForegroundColor Gray “Item contains:”

   

 

    Write-Host -ForegroundColor Gray “Currently working on : “ -NoNewline

    $ImportItem.Uri.AbsoluteUri

 

    # First let us work on the Current navigation items

    # For the first parameter in Ex/IncludeInNavigation we need to know:

    # https://msdn.microsoft.com/en-us/library/office/microsoft.sharepoint.publishing.navigation.portalnavigation.includeinnavigation.aspx

    # useGlobal means true for global and false for current

 

    if($ImportItem.Current)

    {

        # Current and yes we want to see it

        $PuWeb.Navigation.IncludeInNavigation($false, $ImportItem.UniqueId)

    }

    else

    {

        # Current and we want to hide the item

        $PuWeb.Navigation.ExcludeFromNavigation($false, $ImportItem.UniqueId)

    }

   

    ## Now let us work on the Global naviation items

    ## For pages in the SiteCol it makes sense

    ## For pages in SubSites only Current let see us changes

      

    if($ImportItem.Global)

    {

        # Global and yes we want to see it

        $PuWeb.Navigation.IncludeInNavigation($true, $ImportItem.UniqueId)

    }

    else

    {

        # Global and we want to hide the item

        $PuWeb.Navigation.ExcludeFromNavigation($true, $ImportItem.UniqueId)

    }

 

    # Now we need to update it

    $PuWeb.Update()

    $PuWeb.Web.Dispose()

    $SPWeb.Dispose()

 

    $i++

} while ($i -lt $ImportArray.Count)

 

Write-Host -ForegroundColor Green “We are done with “ ($ImportArray.Count1) ” Pages.”

 

You can run from your SharePoint 2013 Management Shell similar to: C:\Users\Administrator.Contoso\Documents\Import-Pages.ps1 –ImportFile “C:\Users\Administrator.Contoso\Documents\Export-Contoso-Pages.xml”

References during my journey to develop this script:

PublishingPage.IncludeInCurrentNavigation property
https://msdn.microsoft.com/en-us/library/office/microsoft.sharepoint.publishing.publishingpage.includeincurrentnavigation.aspx

PublishingWeb.IncludeInGlobalNavigation property
https://msdn.microsoft.com/en-us/library/office/microsoft.sharepoint.publishing.publishingweb.includeinglobalnavigation.aspx

PortalNavigation.ExcludeFromNavigation method
https://msdn.microsoft.com/en-us/library/office/microsoft.sharepoint.publishing.navigation.portalnavigation.excludefromnavigation.aspx
The faster method instead of using the property when writing.

PortalNavigation.IncludeInNavigation method
https://msdn.microsoft.com/en-us/library/office/microsoft.sharepoint.publishing.navigation.portalnavigation.includeinnavigation.aspx
The faster method instead of using the property when writing.

A different way and for Pages:
http://stackoverflow.com/questions/228145/how-do-i-programatically-turn-off-show-pages-in-navigation-for-sharepoint

Using the Export-Clixml Cmdlet
https://technet.microsoft.com/en-us/library/ee176824.aspx

Using the Import-Clixml Cmdlet
https://technet.microsoft.com/en-us/library/ee176873.aspx

PowerShell Looping: Understanding and Using Do…While
https://blogs.technet.microsoft.com/heyscriptingguy/2014/05/05/powershell-looping-understanding-and-using-do-while/

about_Comparison_Operators
https://technet.microsoft.com/en-us/library/hh847759.aspx

I tested on a SharePoint 2013 environment, but it may also work on SharePoint 2016 environments. In case you are working with large lists of changes, it might be also an idea to increase the performance by checking whether you need to set $PuWeb again or you reuse it. Also before calling $PuWeb.Update() or dispose it, it would need some more logic to be able to reuse the object.

Comments (0)

Skip to main content