Subscribe in a reader

Add to Technorati Favorites Sharepoint Nirvana | Export Publishing Page Content to XML

Export Publishing Page Content to XML

by Jamie McAllister 15. October 2008 19:27

We had a recent requirement to export all our variation content out as an XML file for an external organisation. You can kind of do this OOTB in Site Content and Structure -> Export Variation, but it’s not nice. You have no control over the schema you get the content in, or the identifiers of the content, and it’s all wrapped in a CAB file with loads of other junk. (Not to mention that I’ve run into an install where their ISA server settings blocked that file – schoolboy error! )

 

So, I set about writing a custom solution to the problem that gave me more control. I made the following decisions;

 

To control what content fields are exported using the same Translatable Columns settings that Sharepoint uses when you export variations. ( _Layouts/TranslatableSettings.aspx ).

 

To provide sufficient identifiers with the content so that I could conceivably use a similar route to re-import changed content if that requirement arises in future.

 

To download the content as a well formed XML file.

 

To access the export feature via a Site Action menu option.

 

[Btw you might want to read this post in conjunction with http://www.the-north.com/sharepoint/post/Propagating-Document-Library-Items-In-MOSS-Variations-(in-the-same-way-as-Pages).aspx as there are some similarities in how the development was done.]

 

So, how is it all done? It goes like this;

 

 Translatable Columns. 

This took a bit of digging, but I found that these are stored as an xml file within a property of SPList.RootFolder of the Relationships List. This code returns the xml;

 Guid guid = new Guid(publishingweb.AllProperties["_VarRelationshipsListId"].ToString()); 

string translatableCols = publishingweb.Lists[guid].RootFolder.Properties["TranslateFields"] as string;

  

The XML format didn’t suit what I wanted to do with this, so I created a Generic Sorted Dictionary to hold the Column Name and Field GUID, and copied those values in;

 

SortedDictionary<string, Guid> translatableColumns = new SortedDictionary<string, Guid>();

 

 I also then created an XmlDocument to fire my content extracts into as I went along; 

private XmlDocument contentExtract; 

Obtain the Content and its Identifiers 

If you’ve read any of my prior blog posts, you’ll have seen my recursion style code to recurse through my webs. I utilised this again to visit all my Publishing Pages within the Site Collection. I also checked the Moderation Status of the pages etc so I knew I was getting what I wanted. 

Once I had my publishing page instance (pp) it was time to retrieve the values of any fields detailed in translatableColumns; 

foreach (Guid g in translatableColumns.Values) 

string pageContent = SPHttpUtility.HtmlEncode(pp.Fields[g].GetFieldValueAsHtml(pp.ListItem[g])); 

if (pageContent.Length > 0) //We don't need the empty ones 

//Pop the fields internal name and the field Guid into XML properties

attributeFieldName.Value = pp.Fields[g].InternalName;

attributeGuid.Value = g.ToString(); 

//Pop the actual page content into the InnerText of the node

newFieldNode.InnerText = pageContent;  

Download the Content as an XML File 

So, I’ve got my XML file now. The next step is to throw it out as an XML file. This is very easy, because of the way I packaged this. I’ve created this whole solution as an ASP.NET Code Behind file. Andrew Connell detailed the technique here; http://www.andrewconnell.com/blog/articles/UsingCodeBehindFilesInSharePointSites.aspx My page is called ManageVariationsContent.aspx because I can’t stop my naming conventions getting verbose. J 

As such, I have access to the Response object so I simply write;  

Response.AddHeader("Content-disposition", "attachment;filename=ContentDownload.xml");

Response.ContentType = "application/octet-stream";

Response.BinaryWrite(System.Text.UTF8Encoding.UTF8.GetBytes(contentExtractXMLAsString));

Response.Flush();

Response.End();

 

When the code executes my browser receives the file and I can save or open it. Really neat!

 

 Putting it into Site Actions 

All my code has been written as a Feature. To create my SIte Actions menu item I place the following XML in my Element Manifest file (element.xml);

 

<CustomAction Id = “YourGuid”

GroupId = “SiteActions”

Location = “Microsoft.Sharepoint.StandardMenu”

Sequence = “1000”

Rights="ManageSubWebs"

Title = “Your Title”>

<UrlAction Url=”javascript:window.location= ‘{SiteUrl}/ManageVariationsContent.aspx?source=’ + window.location”/>

< /CustomAction>

 

GroupId and Location are what place it in the Site Actions menu. Since this is a fairly priviledged action I specified a Rights attribute so that only someone who can manage sub webs will ever see this Custom Action. (Check out the SPBasePermissions enum on MSDN to see what other values are available for that property).

I pass the site url as a parameter in UrlAction as it gets used in some of the code on my application page – but it’s not of major importance.

 

 Finally 

If you compile this all up in a Feature, and install/activate it you’ll get a new Site Action with the title you specified. Going through to your action page allows you to trigger the extract and download an XML file with all your content.

 

This method gives you a lot of control over what you extract. It also presents many of the steps you might need to push the content back in again (perhaps after you had the variation content translated).

 

You could also bend the code that interrogates publishing page fields to work in a solution for ad-hoc translation when items are published to variations. (But we’ll leave that for another blog post!)

Tags: , ,

Comments

1/31/2009 12:52:59 AM #

Basilios

Hello Jamie,
Thanks for all the great articles. They have been a big help in my learning of SharePoint.

The above article looks like what I need. We are in the process of translating our website variation from English to Italian and I am trying to figure out the best way to do that other that copy/pasting the content (130 pages) into a word document and handing it over for translation and then copy/pasting it back in to the site.

I need an easy way (if there is one) to extract the translatable Columns in a file like an XML file so I can be able to import it back in once its translated.
Is this what your article explains?

I am not that experience with SharePoint as far as programming goes. I am can get around everything else okay.
I am not quite sure I understand when and how I place your code above to take effect for what I need.

Any help? Suggestions?

Basilios United States |

2/19/2009 4:19:29 PM #

Jamie McAllister

Basilios,

Apologies for the late reply. The article, and it's sister article about importing content are exactly what you need. If you follow the code examples, put it together it your own solution it will provide you with enough functionality to export your variation content to XML, get it translated, then import it back into the pages. It works in the real world, it has been tried and tested!

Jamie

Jamie McAllister United Kingdom |

6/10/2009 12:35:17 AM #

Mehmet Kazgan

Hi Jamie,

I am getting an error "Value cannot be null. Parameter name: s " when I run this as a web part. Thanks again for this post and follow up for assistance.

You clearly rock!
Mehmet

Mehmet Kazgan United States |

6/20/2009 11:06:10 AM #

tukang nggame

great post, Thanks for taking the time to share this with us

tukang nggame United States |

12/13/2010 2:40:00 PM #

Akash

HI Jamie,

Thanks for the exhaustive information on the approach. However, can you please tell me as to whether there is any OOTB solution for a similar requirement in sharepoint 2010?

That's because my requirement is to provide maximum OOTB solutions, and this approach will involve customization.

Best Regards,
Akash

Akash India |

12/13/2010 3:00:35 PM #

Jamie

Akash,

You have the option of using the Export/Import Variation options that you get in the Manage Site Content view of your Variation sites. This uses the Content Deployment API. I provide the alternative in this article because I needed the extra control and my own XML schema (and the OOTB solution didn't work too well).

Further you now have the MUI in 2010 which might meet some of your needs. http://jopx.blogspot.com/2010/01/multilingual-user-interface-mui-in.html

Jamie

Jamie United Kingdom |

12/13/2010 3:14:29 PM #

Akash


Yes, I have tried the option to Export/Import Variation available OOTB. However, there are some issues with that option:

1) The Resx file generated, which is a well formed xml gives the data on the site level, and not the page level content. ie, Suppose I have CEWP on a page with data in it, the file doesnt give that data.

2) There is only an option to bulk export for the source language, and we cannot select content to export.

Guess then the only option is to go for customization, as none of the approaches are giving me the page level xml as an output.

Best Regards,
Akash

Akash India |

12/13/2010 3:21:04 PM #

Jamie

Yes, I'm with you on all points, so you see why I created a custom solution. I have extended my solution beyond the one posted to get CEWP content etc. It's not too hard to achieve. Best of luck.

Jamie United Kingdom |

12/13/2010 3:24:34 PM #

Akash


Thank you Jamie for all the information and guidance :). Will the customization option now.

Akash India |

About the author

Jamie McAllister Jamie McAllister is a SharePoint consultant based in Geneva, Switzerland.

Book List

      
      
      
      

    Disclaimer: The software and source code on this website is provided "AS IS"
    with no warranties of any kind. The entire risk arising out of the use or
    performance of the software and source code is with you.