Introduction
We are using SharePoint’s Managed Metadata Service Application’s Content Type Hub model to manage the Content Types and Site Columns.
I’d highly recommend the following Technet Article for more information, Plan to share terminology and content types
Anyway, the approach to adding new metadata to the Content Types is using Feature Upgrading which has been interesting and has caused a few problems, which I have blogged about in the past.
Whilst researching the different options for the upgrade process I stumbled over a problem when using PowerShell to add a field to the Site Collection. This problem really only appears when you are using the Field within a Content Type that is being published to other site collections as part of a Content Type Hub.
The PowerShell worked and the Site Column was successfully created using the method. SPFieldCollection.AddFieldAsXml() function. However, when it came to pushing the changes out to the other site collections using the Managed Metadata’s Content Type Subscriber timer job the following errors were logged to the SharePoint ULS Log:-
- “The element ‘FieldTemplate’ in namespace ‘urn:deployment-manifest-schema’ has invalid child element ‘Field’ in namespace ‘http://schemas.microsoft.com/sharepoint/’. List of possible elements expected: ‘Field’ in namespace ‘urn:deployment-manifest-schema’.”
- “Received an error message from import: The element ‘FieldTemplate’ in namespace ‘urn:deployment-manifest-schema’ has invalid child element ‘Field’ in namespace ‘http://schemas.microsoft.com/sharepoint/’. List of possible elements expected: ‘Field’ in namespace ‘urn:deployment-manifest-schema’.. The recommendation is:”
- “A content type failed to be syndicated: System.Xml.Schema.XmlSchemaValidationException: The element ‘FieldTemplate’ in namespace ‘urn:deployment-manifest-schema’ has invalid child element ‘Field’ in namespace ‘http://schemas.microsoft.com/sharepoint/’. List of possible elements expected: ‘Field’ in namespace ‘urn:deployment-manifest-schema’. “
Investigation
The investigation started by looking at the process of adding the field to SharePoint.
The process being used is as follows:-
- Load a SharePoint Elements file which has fields defined in it.
- An example of the element.xml file is shown below
<Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <Field ID="{38384FAD-5BF2-42D6-9243-5BE95F17E5FD}" Type="Text" Name="ITSPFieldName" StaticName="ITSPFieldName" DisplayName="iThink SharePoint Field" Description="Field does something" Group="iThink SharePoint Site Columns" /> </Elements>
- Load the file into PowerShell using the Get-Content Cmdlet
- Get a reference to the Content Type Hub using Get-SPSite
- Get the <Field /> element
- Add a field using the <Field />element and the Site Collection’s Root Web Fields property and AddFieldAsXml() function
Here is a snippet of the PowerShell script that was being executed to do the above:-
$contenttypehub = Get-SPSite -Identity http://sharepoint/hub; [xml]$elementFile = Get-Content .\myelement.xml; $fieldXml = $elementFile.Elements.Field[0]; $addedFieldName = $contenttypehub.RootWeb.Fields.AddFieldAsXml($fieldXml.OuterXml); if($addedFieldName -ne $null) { Write-Host "Added Field with InternalFieldName: " $addedFieldName; } else { Write-Warning "Failed to Add Field with Xml: " $fieldXml.OuterXml; }
Once the script has run then the field is created and is available for assigning to the Content Type. The field is added to the Content Type successfully. However as mentioned previously when the Content Type Subscriber Hub Timer job is run then the errors are displayed about the Field’s SchemaXml .
So what’s going wrong?
Well after examining the Field’s SchemaXml property, I could see the issue.
The field’s schema was displayed using the following script:-
$fieldName = "FOSScannedDocumentId"; $contenttypehub = Get-SPSite -Identity http://sharepoint/hub; $checkField = $contenttypehub.RootWeb.Fields | ?{$_.InternalName -like $fieldName}; $checkField.SchemaXml;
The output of the command showed the Field’s Schema Xml had an added Element as shown below:-
<Field ID="{38384FAD-5BF2-42D6-9243-5BE95F17E5FD}" Type="Text" Name="ITSPFieldName" StaticName="ITSPFieldName" DisplayName="iThink SharePoint Field" Description="Field does something" Group="iThink SharePoint Site Columns" xmlns=" http://schemas.microsoft.com/sharepoint/" />
So what was happening, well PowerShell is being well behaved and adding the namespace attribute from the parent <Elements> node to this child node. Unfortunately SharePoint is not expecting this additional attribute as part of the Field’s SchemaXml and it causes the validation of the Xml to fail. Hence the XmlSchemaValidationException.
Solution
The solution was to modify the string being passed into the AddFieldFromXml() function.
This was achieved by modifying the script to remove the xmlns attribute :-
$removeNamespaceString = 'xmlns="http://schemas.microsoft.com/sharepoint/"'; [xml]$elementFile = Get-Content .\myelement.xml; $fieldXml = $elementFile.Elements.Field[0]; $fieldXmlString = $fieldXml.OuterXml.Replace($removeNamespaceString, ""); $addedFieldName = $contenttypehub.RootWeb.Fields.AddFieldAsXml($fieldXmlString);
This script will find the string with attribute name of xmlns and replace it with a blank string.
Now, when the Field is added using this fixed version of the <Field/> element the Content Type Subscription timer job completes successfully!