Monday 19 August 2013

Export document set to XML

This script pulls a document set out of SharePoint and saves it to your hard drive.

#load SharePoint Powershell snap in
Add-PSSnapin "Microsoft.Sharepoint.PowerShell" -ErrorAction SilentlyContinue

<#
.Synopsis
   Save document set to hard drive
.DESCRIPTION
      Iterates through each tender in document set and procededs to save them to the local hard drive.
.EXAMPLE
   retrieve-ccwTenders -siteUrl http://wingtipserver -listName MyDocumentSet -savePath c:\
#>               
function retrieve-ccwTenders
{
    [CmdletBinding()]
      param(
            #Site url for the sharepoint collection
            [Parameter(Mandatory=$true,
                           HelpMessage="Enter in the site URL where the Tenders Documnet set resides")]
            [ValidateScript({Get-SPSite -Identity $_ | Select-Object -Property Exists -ErrorAction SilentlyContinue})]
            [string]$siteUrl,
            #The name of the documents set
            [Parameter(mandatory=$true,
                           HelpMessage = "Enter in the Display Name of the Document set")]
            [string]$listName 
            #The path where to save your Tenders
            [Parameter(Mandatory=$true,
             HelpMessage = "Enter the file path where to save your tenders document set")]
            [ValidateScript({Test-Path $_})]
            [string]$SavePath
      )

    Begin
    {
            Clear-Host
           
            #get site using user supplied parameter
            $site = Get-SPSite($siteUrl)

            #get the Root web of the site
            $rootWeb = $site.RootWeb
    }
   
      Process
    {
            #get Documnet Set instance
            $DocumentSet = $rootWeb.Lists.TryGetList($listName)
     
            #make sure the document set is not null
            if($DocumentSet -ne $null)
            {
                  #iterate through all documents sets(tenders)
                  $DocumentSet.Items | foreach {
                        #ensure that item is a document set
                        if($_["HTML File Type"] -eq "SharePoint.DocumentSet")
                        {
                              SaveDocSetMetadata $_
                        }
                        elseif($_["HTML File Type"] -eq $null)
                        {
                              #save the document to folder & Append File metadata to XML Document
                              SaveDocSetDocument $_
                        }
                  }
            }
    }
   
      End
    {
            $rootWeb.Dispose()
            $site.Dispose()
    }
}

function SaveDocSetMetadata($docset)
{
      $DocsetSavePath = [System.IO.Path]::Combine("$savePath\DocumentSet", $docset.Title)
           
      #create folder on HD to store Tender Data
      if((Test-Path $DocsetSavePath) -eq $false)
      {
            New-Item -ItemType directory -Path $DocsetSavePath | Out-Null
      }
                             
      #create xml object in memory
      $docsetXML = New-Object Xml
                             
      #create xml declaration
      [System.Xml.XmlDeclaration] $xmlDeclaration = $docsetXML.CreateXmlDeclaration("1.0", "UTF-16", $null);
      $docsetXML.AppendChild($xmlDeclaration)  | Out-Null
                             
      #create Root Node
      $root = $docsetXML.CreateElement("DS")   
      $docsetXML.AppendChild($root) | Out-Null
           
      #create metadata node
      $metadata = $docsetXML.CreateElement("Metadata")
      $root.AppendChild($metadata)  | Out-Null
     
      #get relevent metaData for tender
      $docset.Fields | foreach {   
            $data = $docsetXML.CreateElement("Data")
           
            $data.InnerText = $docset[$_.Title]
            $data.SetAttribute("Title", $_.Title)
            $data.SetAttribute("InternalName", $_.InternalName)
            $data.SetAttribute("ReadOnly", $_.ReadOnlyField)
           
            $metadata.AppendChild($data)  | Out-Null 
      }
           
      #save xml object to file
      $temp = $docsetXML.Save("$DocsetSavePath\Tender.xml")
     
      Write-output "Created $DocsetSavePath/Tender.xml"
}

function SaveDocSetDocument($docset)
{
      $wc = New-Object System.Net.WebClient
     
      $source = $docset["Encoded Absolute URL"]
      $folder = $docset["Path"].Substring($docset["Path"].lastindexof("/")+1)
      $fileName = $docset["FileLeafRef"]
     
      $destination = [System.IO.Path]::Combine("$savePath\DocumentSet", $folder)
                 
      Try
      {
            $wc.DownloadFile($source, [System.IO.Path]::Combine($destination, $fileName))
      }
      Finally
      {
            $wc.Dispose()
      }

      #Get the xml File path
      $xmlPath = [System.IO.Path]::Combine($destination, "Tender.xml")
                       
      #get the xml document
      [xml]$docsetXML = Get-Content -Path $xmlPath
     
      #get the last element in the xml document
      $lastChild = $docsetXML.DS.get_LastChild()
           
      #check if the last element is <files />, create one if it isn't
      if($lastChild.Name -eq "Files")
      {
            $files = $lastChild
      }
      else
      {
            $files = $docsetXML.CreateElement("Files")
      }
           
      #grab the <files /> element
      $filesNode = $docsetXML.DS.AppendChild($files)
                       
      #create a <file /> element         
      $file = $docsetXML.CreateElement("File")

      $file.SetAttribute("ContentType", $docset["Content Type"])
      $file.SetAttribute("SortOrder", $docset["Sort Order"])
      $file.SetAttribute("FilePath"$folder + "\" + $fileName)
      $file.SetAttribute("urlPath", $docset["Server Relative URL"])
           
      #append the <file /> element to the <files /> element
      $file = $filesNode.AppendChild($file)  | Out-Null
           
      #save xml changes
      $docsetXML.Save($xmlPath)

}