If you've read some of my earlier posts you'll know that I've been working on 3 commands to enable replacing content throughout the site in order to deal with the broken links I've encountered as a result of moving so many sites around for our upgrade.
The first command was gl-replacefieldvalues and the second command was gl-applyupgradeareaurlmappings. This third command, gl-replacewebpartcontent, is focused on replacing content in various built-in web part types. The code for the command, and even the usage of the command, is similar in many respects to the gl-replacefieldvalues command. There are a series of methods used to handle the different scope options that can be passed in and then a primary method which handles the processing of the various files.
Once the web parts have been identified on the page this primary method calls another method based on the web part type. These methods that take in a web part as a parameter are fairly similar in structure with the core difference being what properties are evaluated and modified as each web part type is considered independently. I'm currently only considering the following web parts: ContentEditorWebPart, PageViewerWebPart, ImageWebPart, SiteDocuments, SummaryLinkWebPart, DataFormWebPart, and ContentByQueryWebPart. The last two are only really helpful when the value you are replacing is a List ID - I use the methods that handle these two web part types in my gl-repairsitecollectionimportedfromsubsite command, gl-convertsubsitetositecollection command, and my gl-moveweb command in order to retarget web parts that were hard coded to point to a specific List ID which would have changed as a result of the move.
There's quite a bit of code for this command but most of it is more or less cookie cutter so I'll only show a portion of it. The following code shows the primary decision maker method which determines which web part method should be called. I've also included one method showing how I handle the ContentEditorWebPart - remember that each web part will have it's own way of setting its content.The syntax of the command can be seen below:
C:\>stsadm -help gl-replacewebpartcontent stsadm -o gl-replacewebpartcontent Replaces all occurances of the search string with the replacement string. Supports use of regular expressions. Use -test to verify your replacements before executing. Parameters: [-url <url to search>] -searchstring <regular expression string to search for> -replacestring <replacement string> -scope <Farm | WebApplication | Site | Web | Page> [-webpartname <web part name>] [-quiet] [-test] [-logfile <log file>] [-publish] [-unsafexml (treats known XML data as a string)]
As with the other content replacement commands that I created I strongly suggest that you run the command in test mode (by passing in the "-test" parameter) before executing the command for real. This will enable you to verify all replacements that will occur before letting them actually happen.
Here's an example of how to replace all occurances of the search string "/divisions/humanresources/" (case insensitive) with "/hr/" for all web parts within the "intranet" web application:
stsadm –o gl-replacewebpartcontent -url "http://intranet" -scope webapplication -searchstring "(?i:/divisions/humanresources/)" -replacestring "/hr/" -publish -logfile "c:\replace.log"
You can also pass in a web part name and it will only make changes to web parts that match the specific name (probably not very useful with such a broad scope).
Update 11/28/2007: I've added a new parameter, "unsafexml", which if passed in will result in replacement code treating known XML data as a flat string rather than attempting to load the XML into an XmlDocument object and replacing just text data. This was necessary due to the fact that Microsoft stores invalid XML in the DataFormWebPart's ParameterBindings property (Microsoft is doing a lot of funky stuff to get around the fact that they are doing this and it wasn't something that I felt safe about reproducing so I decided to just add this flag so that if you knew your replacement was safe then you'd still be able to use the command). At this point only the DataFormWebPart is affected by this parameter. As always, make sure you use the "test" parameter before running without it.