Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / productivity / SharePoint

Custom XML Mapping of Content Control in a SharePoint Document Library Template

5.00/5 (1 vote)
17 Mar 2014CPOL5 min read 12.1K  
Custom XML Mapping of Content Control in a SharePoint Document Library Template

After a long time (was in a busy schedule of establishing family after my marriage :) ), I thought I will post this article for setting the XML mapping of content control in a Word document template for SharePoint Document Library. To be frank, in most of the cases, we are / will be using QuickParts Add-in to add the content controls which are already mapped with SharePoint ContentType fields. But in this article, I will be explaining how to set up a document template for a document library without touching the QuickParts Add- in. Sometimes this will be helpful to the developers who are programmatic-ally/dynamically creating document templates or content controls to document templates. To make this article in one line, it's about setting XPath, Prefix Mapping for content controls using SetMapping function of XMLMapping property of content control, like contentControl.XMLMapping.SetMapping(Xpath,PrefixMapping).

These are things that you should have handy with you before starting this exercise.

  1. A Document Content Type with some site columns referred inside – Say, we will name it as “ExpenseContentType” that have 2 site columns (SC_ExpenseName, SC_ExpenseCount)
  2. A Document Library created which will have content type that is mentioned on the above step (Step 1) – say, ExpenseDocumentLibrary.
  3. Word Content Control Tool Kit – Download this toolkit. This is just for the analysis purpose of the template or to understand what is happening behind the scenes.
  4. Visual Studio – Just in case you need to code the logic for XML mapping (Code is embedded at the bottom of the post)

So, let's start from the document library (ExpenseDocumentLibrary).

Step 1

Go the document library setting –> ContentType (ExpenseContentType) –> Advanced Settings

Here on the Advanced setting page of the Document library Content Type, click on the Edit Template link (see image below) . This will open a blank document template in Microsoft Word. Save this locally on your machine with any user friendly name, say ExpenseTemplate.docx.

Edit Template from the Document ContentType of the document library

Step 2

For analysis, open the locally saved blank template using the Word Content Control toolkit. We can see the content type fields on the custom XML parts of the document. This means the ContentType related data like Fields, etc. are there in this document in XML(XSD) format. Since it's a blank document, there is no matter in the Content Controls section.

Blank document

Step 3

Let us add some content controls to this document template. For that, open the Word document using Microsoft Word and from Developer tab, add 1 or 2 plain text content controls to the document as if it resembles a template. (See image below.) Name the content controls exactly as the Site Columns name in ContentType. This means, name Expense Name content control as “SC_ExpenseName”.

Image 4

Save this document after adding the controls.

Step 4

Re-open the document in the Word Content Control Tool Kit. Now we can observe that on the content controls section, it is showing the control entries without having its XPath set with ContentType Fields inside the file. (See the image below). Basically, XPath and Prefix mapping of the Custom XML parts shown on the right pane for the each field need to be mapped with content control.

Image 5

Step 5

In this step, we will set the mapping between the content controls and ContentType fields. Actually, we can set mapping using Word Content Control Toolkit itself, but it will become a manual process. Better we will do it “programmatic-ally” :).

For doing this, I am creating a Word Add-In project in Visual Studio. So open a Visual Studio Instance –> New Project –> Word Add – In (see image below).

Image 6

Give any user friendly name to the project. After that, Add a “Ribbon” into this Add- in project (Right Click on Project –> Add –> New Item –> Ribbon (see image below)).

Image 7

Again, give a user friendly name to the ribbon. On the visual designer of the ribbon, add a button (label it as “Set Mapping”) and on the click event of button, we will write some code as shown below:

C#
///<summary> 
/// Click event of the Set Mapping button
/// </summary>
///
///
private void button1_Click(object sender, RibbonControlEventArgs e)
{
    //Accessing the active document
    Document document = Globals.ThisAddIn.Application.ActiveDocument;
    string nsURI = string.Empty;
    
    //retrieving the content control collection of the active document.
    ContentControls contentControls = document.ContentControls;
    
    //Looping through the content Control collection.
    foreach (ContentControl cntntCtrl in contentControls)
    {
    
        var ctrlTitle = cntntCtrl.Title;
        //Setting the XPath for each control. 
        //This is under a condition that name of the Content type site column /field
        // and content control name & tag is exactly same.
        string xpath = "/ns0:properties[1]/documentManagement[1]/ns1:" + 
        ctrlTitle + "[1]";
        
        //Private function to get the NameSpace URI of the content type field
        nsURI = GetXSDNameSpaceURI(document, cntntCtrl);
        
        //Mapping the content control.
        bool isMapped = cntntCtrl.XMLMapping.SetMapping
        ("/ns0:properties[1]/documentManagement[1]/ns1:" + 
        ctrlTitle + "[1]", 
        "xmlns:ns0='http://schemas.microsoft.com/office/2006/metadata/properties' 
        xmlns:ns1='" + nsURI + "'", null);
        
        if (isMapped == true)
        { MessageBox.Show("Mapping successfully done...!"); }
        else
        { MessageBox.Show("Error in XML Mapping"); }
    }
}

/// <summary> 
/// private function to get the namespace URI of the content type.
/// </summary>
///
///
///
private string GetXSDNameSpaceURI(Document document, ContentControl control)
{
    string nsURI = string.Empty;
    CustomXMLParts xmlParts = document.CustomXMLParts.SelectByNamespace
    ("http://schemas.microsoft.com/office/2006/metadata/properties");
    foreach (CustomXMLPart xmlPart in xmlParts)
    {
        XmlDocument XDoc = new XmlDocument();
        XDoc.LoadXml(xmlPart.XML);
        XmlNodeList result = XDoc.GetElementsByTagName(control.Title);
        nsURI = result[0].NamespaceURI;
        break;
    }
    
    return nsURI;
}

Build the project and press F5. This will open a default word document. Close that document and open our document library template where we have add content control. Find the ribbon that we have created on the opened document and press the button “Set mapping”. This will set the XPath mapping for each content control and throw a message box saying “Mapping successfully done…!”. (See image below.)

Image 8

Now I will explain what actually the above code does. Basically, it iterates through the content controls collection and by using each content control’s title, it's creating an “XPathstring and “Prefix mapping” using the content type namespace URI. The key player is SetMapping function of the content control’s XMLMapping property. This function is used to set the mapping for the content control. The SetMapping function can be called on the event after the control adding to make it more clean. But since this is a POC, we will use iteration logic. The entire article is based on the SetMapping function to make link between content control and content type.

Now just open the document in the Word Content Control toolkit and see the XPath set against each content control. (See image below.)

Image 9

This is the time to upload this document template back into SharePoint. Go to the Advanced settings of the Document library content type and upload the template using “upload a new document template”. After the uploading is over, try adding document files which have data inserted. You can see content control data getting binded with content type columns within the document library.

I hope you enjoyed/understood this article. Thanks for reading. Comments are invited.

Image 10 Image 11

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)