public/Save-SkylineContentTypeSchema.ps1

Function Save-SkylineContentTypeSchema {
    <#
    .SYNOPSIS
    Extracts the PnP Provisioning Schema XML for the specific site content type(s)
     
    .DESCRIPTION
    Extracts the PnP Provisioning Schema XML for the specific site content type(s)
     
    Reference: https://github.com/SharePoint/PnP-Provisioning-Schema
 
    .EXAMPLE
    Save-SkylineContentTypeSchema -ContentType "ContentType1" -Path "C:\ProvisioningSchemas\ContentType1.xml"
 
    .PARAMETER ContentType
    Title of the target content type. May pass multiple content types as -ContentType "ContentType1", "ContentType2"
 
    .PARAMETER Path
    Path to export the provisioning schema to. Example: C:\ProvisioningSchemas\ContentType1.xml
 
    .PARAMETER Web
    The web to apply the command to. Omit this parameter to use the current web.
    #>


    [cmdletbinding()]
    param(
        [parameter(Mandatory = $True)]
        [string[]]$ContentType, 
        [parameter(Mandatory = $True)]
        [string]$Path,
        [Microsoft.SharePoint.Client.Web]$Web
    )

    Process
    {
        Write-Debug ( "Running $($MyInvocation.MyCommand).`n" + "PSBoundParameters:`n$($PSBoundParameters | Format-List | Out-String)")

        Try
        {     
            $PSBoundParameters.Remove("ContentType") | Out-Null
            $PSBoundParameters.Remove("Path") | Out-Null

            $Directory = Ensure-SkylineDirectory $Path
            $FileName = Get-SkylineFileName $Path
            $Path = "$Directory\$FileName"
            $TemporaryPath = "$Directory\$FileName.temp.xml"

            Get-PnPProvisioningTemplate -Handlers ContentTypes, Fields -Out $TemporaryPath -Force @PSBoundParameters

            [XML]$SchemaXml = Get-Content -Path $TemporaryPath

            #Trim down to only the content type we want
            $ContentTypeNodesToRemove = @($SchemaXml.Provisioning.Templates.ProvisioningTemplate.ContentTypes.ContentType | Where-Object {!$ContentType.Contains($_.Name)})
            $ContentTypeNodesToRemove | ForEach-Object {$SchemaXml.Provisioning.Templates.ProvisioningTemplate.ContentTypes.RemoveChild($_) | Out-Null}

            #Get fields of the content type we want
            $ContentTypeNodesToKeep = $SchemaXml.Provisioning.Templates.ProvisioningTemplate.ContentTypes.ContentType
            $FieldNodesToKeep = @($ContentTypeNodesToKeep | ForEach-Object {$_.FieldRefs.FieldRef | ForEach-Object {$_.Name}})
            
            #Trim down site fields to only the ones referenced in the content type we want
            $FieldNodesToRemove = @($SchemaXml.Provisioning.Templates.ProvisioningTemplate.SiteFields.Field | Where-Object {$FieldNodesToKeep -NotContains $_.Name})
            $FieldNodesToRemove | ForEach-Object {$SchemaXml.Provisioning.Templates.ProvisioningTemplate.SiteFields.RemoveChild($_) | Out-Null}

            #Save the remaining XML
            $SchemaXml.Save($Path)

            Remove-Item -Path $TemporaryPath -Force
        }
        Catch
        {
            Throw $_
        }
    }
}